Предположим, что эта цепочка ссылок 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 исправлениям, оба из которых работают .
GSOurAutomation.Framework.White
Хотя мой конкретный экземпляр исправлен, может ли это обновление помочь кому-нибудь объяснить причину этого? Если нет, шимми получает галочку :) для указания в правильном направлении.