成员访问调用无法编译,但静态调用可以。

10
今天我在构建我们公司的解决方案时遇到了一个有趣的问题,我想问问你们是否知道为什么会发生这种情况。有人告诉我可能是因为我的电脑/Visual Studio 的原因,因为其他人没有遇到同样的问题。
所以我们在项目 A 中有一个方法:
private static string RpcRoutingKeyNamingConvention(Type messageType, ITypeNameSerializer typeNameSerializer)
{
   string queueName = typeNameSerializer.Serialize(messageType);

   return messageType.GetAttribute<GlobalRPCRequest>() != null || AvailabilityZone == null
        ? queueName
        : queueName + "_" + AvailabilityZone;
}

GetAttribute<GlobalRPCRequest>()public static class ReflectionHelpers中定义。

 public static TAttribute GetAttribute<TAttribute>(this Type type) where TAttribute : Attribute;

然后我们有项目B,其中有一个方法:

public static string GetAttribute(this XElement node, string name)
{
   var xa = node.Attribute(name);
   return xa != null ? xa.Value : "";
}

我必须指出,我们在项目A中引用了项目B。现在发生的是,当我尝试构建时,会出现编译错误:

错误966:“System.Xml.Linq.XElement”类型定义在未被引用的程序集中。您必须添加对程序集“System.Xml.Linq,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089”的引用。D:\Repositories\website\website\submodules\core\src\A\Extensions\Extensions.cs 37 13 A

发生的情况是编译器认为我实际上正在使用项目B中的GetAttribute方法(在我看来是这样!)。为什么会这样呢?因为当我尝试导航到GetAttribute时,VS会将我带到正确的方法(即在ReflectionHelpers中的方法)。这可能是因为反射吗?NOTE: 我通过静态调用该方法或在我的项目A中添加对System.Xml.Linq的引用来解决了此问题,但我对VS/语法检查功能的奇怪行为很感兴趣。


你是否引用了包含XElement的程序集?因为它告诉你那就是问题所在,没有提到方法名。我的意思是,你尝试添加System.xml.linq了吗? - D. Ben Knoble
但是你在B项目中做了什么? - D. Ben Knoble
不,我已经在项目A中添加了引用。项目B没有出现任何问题。 - kuskmen
我不确定,但如果你这么说的话...我并不是在寻求错误解决方案,而是在询问奇怪行为的解释。我修复它的方式有什么关系呢? - kuskmen
7
https://dev59.com/DpTfa4cB1Zd3GeqPW-PL#35940354 - Hans Passant
显示剩余4条评论
3个回答

1
我猜测你的函数:private static string RpcRoutingKeyNamingConvention(Type messageType, ITypeNameSerializer typeNameSerializer) 与你的帮助方法签名不匹配,因为你试图返回一个字符串:public static TAttribute GetAttribute<TAttribute>(this Type type) where TAttribute : Attribute; 这个方法期望一个 TAttribute 返回类型。也许你可以尝试修改你的函数RpcRoutingKeyNamingConvention返回 GlobalRPCRequest 并检查编译器是否继续疯狂。

你的辅助方法签名不匹配,因为你尝试返回一个字符串:这是什么意思,因为我试图返回字符串,所以它不匹配我的辅助方法?这种说法太过分了吧? - kuskmen
@Yann REANAUDIN并不是试图返回一个字符串,请看? queueName:queueName +“_”+ AvailabilityZone; - Tokk

1
Visual Studio经常会出现混淆的情况!我在我的VS 2015(.NET 4.6)中尝试重现这种情况,编译工作正常。在Project A中,我不需要添加对System.Xml.Linq的引用。
我猜测这可能是缓存问题。你可以尝试以下步骤:
1. 删除对Project B的引用 2. 清理后重新构建两个解决方案 3. 添加引用回来 4. 重新构建,希望能成功
希望有所帮助,请告诉我 :)

0

我猜这是发生了以下情况:
- B 引用了 System.Xml.Linq
- B 顺利构建。
- 你在 A 中引用了 B
- A 没有引用 System.Xml.Linq
- A 似乎使用了 B 中定义的函数
- 当你尝试构建项目 A 时,它会产生错误

我的理解是否正确?

如果是这种情况,那就很正常。因为一个消费引用(A)的项目必须具有对被引用的内容(System.Xml.Linq)的引用,该内容由其所引用的内容(B)引用。

可以这样想:当你尝试向项目添加 nuget 包时,如果它有依赖关系,nuget 也会安装它。为什么?因为出现了这种情况。

如果我正确理解了你的回答,那么这是完全正常的。


问题是为什么编译器会混淆,当 Visual Studio 的导航清楚地知道哪个方法是正确的(在项目 A 中)时,它会使用项目 B 中的函数?当你回答这个问题时,你将找到原始帖子答案的答案,至少我是这样得到的。请查看我问题下面的评论中的链接,它几乎回答了我所问和想知道的所有问题。 - kuskmen
哈哈哈! 对于我的回答和困惑,非常抱歉我的英语很差。您有权这样做 :-) - zokkan
顺便问一下,你正在使用哪个版本的VS? - zokkan
你的using块中是否同时包含两个版本的命名空间?你尝试过通过提供整个路径来调用方法吗?(例如:A.ReflectionHelpers.GetAttribute) - zokkan
是的,我通过提供整个路径(即静态调用)来解决了编译器的混淆问题。问题是关于混淆而不是如何解决它。 - kuskmen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接