【问题标题】:How To Ensure Correct Extension Method Resolution如何确保正确的扩展方法解析
【发布时间】:2016-10-19 13:24:33
【问题描述】:

我在我的扩展方法解析中看到了一些意外行为,我正试图找出原因。我已经阅读了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 的扩展方法重载:

//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 调用在以下方法之间不明确或 属性:'Extensions.Delete(IOrganizationService,Entity)'和 'Extensions.Delete(IOrganizationService, EntityReference)'

我从我定义的隐式运算符中了解到这一点。我不明白的是,为什么 DLaB.Xrm 命名空间比 DLaB.Xrm.Test 命名空间更接近,即使我没有 using 指令。

【问题讨论】:

    标签: c# extension-methods overload-resolution


    【解决方案1】:

    Eric 的博客中定义了 6 条接近规则:

    1. 在派生类中首先声明的方法比在基类中首先声明的方法更接近。
    2. 嵌套类中的方法比包含类中的方法更接近。
    3. 接收类型的任何方法都比任何扩展方法更接近。
    4. 在嵌套命名空间中的类中找到的扩展方法比在外部命名空间中的类中找到的扩展方法更接近。
    5. 在当前命名空间中的类中找到的扩展方法比在 using 指令提及的命名空间中的类中找到的扩展方法更接近。
    6. 在 using 指令中提及的命名空间中的类中找到的扩展方法(该指令位于嵌套命名空间中)比在 using 指令中提及的命名空间中的类中找到的扩展方法更接近,其中指令位于外部命名空间。

    前 3 个不适用,因为接口没有适用的方法。 第四个是关键。 DLaB.Xrm 位于嵌套命名空间中,即使它位于不同的程序集中。我错误地认为您必须列出扩展方法的 using 指令才能从另一个类访问它。我现在知道嵌套命名空间中的扩展方法是自动可用的。

    将namespace DLaB.Xrm.Tests 更改为namespace NotNested.DLaB.Xrm.Tests 消除了所有紧密规则,并且通过正常的签名重载解决规则解决了模棱两可的调用。我使用的实际修复只是使 Delete 调用泛型,这消除了争用中的两个隐式转换重载,并允许将调用解析为我的首选方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-28
      • 2012-05-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-21
      • 2014-04-02
      相关资源
      最近更新 更多