Почему вызов IEnumerable < string> .Count () создать дополнительную зависимость сборки?

Предположим, что эта цепочка ссылок dll

Tests.dll >> Automation.dll >> White.Core.dll

со следующей строкой кода в Tests.dll, где все строится

result.MissingPaths 

Теперь, когда я изменяю это на

result.MissingPaths.Count()

, я получаю следующая ошибка сборки для Tests.dll «White.UIItem не определен в сборке, на которую нет ссылки. Вы должны добавить ссылку на White.Core.dll». И я не Я не хочу этого делать, потому что это нарушает мои слои.

Вот определение типа для результата, которое находится в Automation.dll

public class HasResult
        {
            public HasResult(IEnumerable<string> missingPaths )
            {   MissingPaths = missingPaths;           }

            public IEnumerable<string> MissingPaths { get; set; }

            public bool AllExist
            {
                get { return !MissingPaths.Any(); }
            }
        }

Внизу цепочки вызовов входной параметр для этого ctor создается через (класс TreeNode находится в White.Core.dll)

assetPaths.Where(assetPath => !FindTreeNodeUsingCache(treeHandle, assetPath));

Почему эта зависимость просачивается при вызове Count () в IEnumerable? Затем я заподозрил, что причиной этого является ленивое вычисление (по какой-то причине) - поэтому я вставил ToArray () в строку выше, но не работал.

Обновление 2011 01 07: Curiouser and Curiouser! dll)

assetPaths.Where(assetPath => !FindTreeNodeUsingCache(treeHandle, assetPath));

Почему эта зависимость просачивается при вызове Count () в IEnumerable? Затем я заподозрил, что причиной этого была ленивая оценка (по какой-то причине) - поэтому я вставил ToArray () в строку выше, но не сработал.

Обновление 2011 01 07: Curiouser and Curiouser! dll)

assetPaths.Where(assetPath => !FindTreeNodeUsingCache(treeHandle, assetPath));

Почему эта зависимость просачивается при вызове Count () в IEnumerable? Затем я заподозрил, что причиной этого является ленивое вычисление (по какой-то причине) - поэтому я вставил ToArray () в строку выше, но не работал.

Обновление 2011 01 07: Curiouser and Curiouser! он не будет построен, пока я не добавлю ссылку на White.Core. Поэтому я добавляю ссылку и создаю ее (чтобы найти неуловимый источник зависимости). Откройте его в Reflector, и единственные ссылки в списке - это Automation, mscorlib, System.core и NUnit. Таким образом, компилятор выбросил ссылку White, поскольку она не была нужна. ILDASM также подтверждает, что здесь нет записи White AssemblyRef.

Есть идеи, как разобраться в этой вещи (в первую очередь по причинам «теперь я хочу знать, почему»)? Какова вероятность того, что это ошибка VS2010 / MSBuild?

Обновление 2011 01 07 # 2 Согласно предложению Шимми, я попытался вызвать метод явным образом как метод расширения

Enumerable.Count(result.MissingPaths)

, и он прекратил копирование (не знаю почему).
Однако после этого я переместил некоторый код, и теперь я получаю ту же проблему в другом месте с использованием IEnumerable - на этот раз чтение и фильтрация строк из файла на диске (совершенно не связанного с White). Похоже, это «устранение симптомов».
var lines = File.ReadLines (aFilePath) .ToArray (); еще раз, если я удалю ToArray (), он снова компилируется - кажется, что любой метод, который вызывает вычисление перечисляемого (ToArray, Count, ToList и т. д.), вызывает это. Позвольте мне попробовать и получить работающее маленькое приложение для демонстрации этой проблемы ...

Обновление 2011 01 07 # 3 Фух! Подробнее .. Оказывается, проблема только в одном исходном файле - этот файл является LINQ-фобичным. Любой вызов метода расширения Enumerable должен вызываться явно. В результате проведенного мной рефакторинга в этот исходный файл был перенесен новый метод, в котором был некоторый LINQ :) По-прежнему не могу понять, почему этот класс не любит LINQ.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using G.S.OurAutomation.Constants;
using G.S.OurAutomation.Framework;
using NUnit.Framework;

namespace G.S.AcceptanceTests
{
    public abstract class ConfigureThingBase : OurTestFixture
    {
      ....
        private static IEnumerable<string> GetExpectedThingsFor(string param)
        {
                // even this won't compile - although it compiles fine in an adjoining source file in the same assembly
                //IEnumerable<string> s = new string[0];
                //Console.WriteLine(s.Count()); 



                // this is the line that is now causing a build failure   
            //  var expectedInfo = File.ReadLines(someCsvFilePath))
//                  .Where(line => !line.StartsWith("REM", StringComparison.InvariantCultureIgnoreCase))
//                  .Select(line => line.Replace("%PLACEHOLDER%", param))
//                  .ToArray();

                // Unrolling the LINQ above removes the build error

            var expectedInfo =
                Enumerable.ToArray(
                    Enumerable.Select(
                        Enumerable.Where(
                            File.ReadLines(someCsvFilePath)),
                            line => !line.StartsWith("REM", StringComparison.InvariantCultureIgnoreCase)),
                        line => line.Replace("%PLACEHOLDER%", param)));

Обновление 2011 01 11 # 4 Сузил его до того, что кажется преступником, но без мотива :)
Возобновил публикацию квеста на выходных ... и, используя вечнозеленый процесс устранения, смог сосредоточиться на неприятном моменте. Проблема заключается в следующей директиве using в исходном файле в Tests.dll

using G.S.OurAutomation.Framework;

. Затем я обратился к наиболее вероятному подозреваемому в этом пространстве имен, и в центре внимания оказались WhiteExtensions.

namespace G.S.OurAutomation.Framework
{
   public static class WhiteExtensions
   {
        public static T PollAndGet<T>(this Window parentWindow, string automationId) where T : UIItem ...
        public static Window WaitForWindowWithTitle(this Application application, string windowTitle) ...
        public static bool HasTreeNode(this Tree treeHandle, string assetPath) ...
        public static HasTreeNodesResult HasTreeNodes(this Tree treeHandle, IEnumerable<string> assetPaths)...
   }
}

Это привело к 3 исправлениям, оба из которых работают .

  1. Превратите методы расширения в обычные статические методы.
  2. Переместите этот класс в подпространство имен GSOurAutomation.Framework.White
  3. Сделайте его внутренним классом (так как он предназначен для внутреннего потребления .. еще раз руководство по выбору самого ограничивающего модификатора доступа меня раздражает.)

Хотя мой конкретный экземпляр исправлен, может ли это обновление помочь кому-нибудь объяснить причину этого? Если нет, шимми получает галочку :) для указания в правильном направлении.

8
задан Gishu 11 January 2011 в 05:41
поделиться