我在扩展方法解析中看到了一些意想不到的行为,并且我试图找出原因。我已阅读Eric Lippert's Closer is Better文章,我仍感到困惑。
首先是呼叫站点:
// Assembly: DLaB.Xrm.2016.Tests
using DLaB.Xrm.Entities;
using DLaB.Xrm.Test;
using Microsoft.Xrm.Sdk;
namespace DLaB.Xrm.Tests
public class TrialClass{
{
public void Delete(){
IOrganziationService service = GetService();
Id<Contact> id = GetId();
service.Delete(id); // Call Site in Question
}
}
}
IOrganizationService使用此签名定义删除方法:
// Assembly: Microsoft.Xrm.Sdk
void Delete(string entityName, Guid id);
我已经在两个不同的程序集中的两个不同的名称空间中定义了IOrganziationService上的Extension方法重载:
//Assembly: DLaB.Xrm.2016
//Namespace DLaB.Xrm
public static void Delete(this IOrganizationService service, Entity entity) { ... }
public static void Delete(this IOrganizationService service, EntityReference entity) { ... }
//Assembly: DLaB.Xrm.Test.2016
//Namespace DLaB.Xrm.Test
public static void Delete(this IOrganizationService service, Id id) { ... }
public static void Delete<T>(this IOrganizationService service, Id<T> entity) where T : Entity { ... }
我还为Id类定义了隐式运算符,将其转换为Entity
或EntityReference
呼叫站点
service.Delete(id)
显示编译器错误: 错误CS0121以下方法或之间的调用不明确 properties:&#39; Extensions.Delete(IOrganizationService,Entity)&#39;和 &#39; Extensions.Delete(IOrganizationService,EntityReference)&#39;
我从我已经定义的隐含算子中理解了这一点。我不理解的是DLaB.Xrm
命名空间比DLaB.Xrm.Test
命名空间更接近的原因,即使我没有使用using指令。
答案 0 :(得分:1)
Eric的博客中定义了6条贴近规则:
前三个不适用,因为没有适用于接口的方法。 第四是关键。 DLaB.Xrm位于嵌套的命名空间中,即使它位于不同的程序集中。我错误地认为你必须列出扩展方法的using指令才能从另一个类访问它。我现在知道嵌套命名空间中的扩展方法是自动可用的。
将namespace DLaB.Xrm.Tests
更改为namespace NotNested.DLaB.Xrm.Tests
会消除所有接近规则,并且通过正常签名重载决策规则解决模糊呼叫。我使用的实际修复只是使Delete调用泛型,这消除了争用中的两个隐式转换重载,并允许将调用解析为我的首选方法。