假设这个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(); }
}
}
在调用链中,通过(TreeNode类在White.Core.dll中)创建此ctor的输入参数
assetPaths.Where(assetPath => !FindTreeNodeUsingCache(treeHandle, assetPath));
为什么在IEnumerable上调用Count()时这个依赖项会泄漏?然后我怀疑懒惰的评估导致了这个问题(出于某种原因) - 所以我在上面的行中插入了一个ToArray()但是没有用。
更新2011 01 07: Curiouser和Curiouser! 在添加White.Core引用之前,它不会构建。所以我添加一个引用并构建它(为了找到难以捉摸的依赖源)。在Reflector中打开它,列出的唯一引用是Automation,mscorlib,System.core和NUnit。所以编译器丢弃了White引用,因为它不需要。 ILDASM还确认没有White AssemblyRef条目。
关于如何深入了解这件事的任何想法(主要是'现在我想知道为什么'的原因)?这是VS2010 / MSBuild错误的可能性有多大?
更新2011 01 07#2 根据Shimmy的建议,尝试将explcitly方法称为扩展方法
Enumerable.Count(result.MissingPaths)
它停止了抄袭(不确定为什么)
但是之后我移动了一些代码,现在我使用IEnumerable在不同的位置获得相同的问题 - 这次是从磁盘上的文件读取和过滤行(完全与白色无关)。好像它是一个'症状修复'
var lines = File.ReadLines(aFilePath).ToArray();
再次,如果我删除ToArray()它再次编译 - 似乎导致可枚举的任何方法(ToArray,Count,ToList等)导致这种情况。让我尝试使用一个有效的小应用来演示这个问题......
更新2011 01 07#3 唷!更多信息..事实证明问题只在一个源文件中 - 这个文件是LINQ-phobic。必须显式调用对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 把它缩小到似乎是perp但没有动机:) 周末恢复了任务......并且使用常绿的消除过程,能够在违规位上划分。 问题是Tests.dll
中源文件中的以下using指令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个修复,两个都有效。
G.S.OurAutomation.Framework.White
虽然我的具体实例已修复,但此更新是否可以帮助某人解释原因?如果没有,那么就可以指向正确的方向。[/ p>
答案 0 :(得分:4)
尝试调用System.Linq.Enumerable.Count(result.MissingPaths)
(带或不带完整的命名空间引用)。
Count
是一种扩展方法,您可以明确地调用它。
Gishu更新后的更新#2:
所有内容的原因相同,函数ToArray
,Count
,ToList
等都是System.Linq.Enumerable
中声明的扩展方法。
BTW,重要:您是否仔细检查过命名空间System.Linq是否已导入(using System.Linq
)到您的文件中?这甚至可以解决你所有的问题。
答案 1 :(得分:1)
编译器可能需要查看White.Core.dll以确定是否在您的类上定义了Count()方法。由于没有使用IEnumerable&lt;&gt;扩展方法的计数因此毕竟不需要White.Core.dll,但它不知道没有检查它。
但我无法解释IEnumerable<string>
的情况如何,除非编译器检查你没有使用协方差?
答案 2 :(得分:0)
如何改变
public HasResult(IEnumerable<string> missingPaths )
{ MissingPaths = missingPaths; }
到
public HasResult(IEnumerable<string> missingPaths )
{ MissingPaths = missingPaths.ToArray(); }
在使用结果的所有情况下,应该消除延迟加载方案。