2016-10-19 6 views
2

拡張メソッドの解決方法で予期しない動作が発生することがあります。その理由を理解しようとしています。私はEric Lippert's Closer is Betterの記事を読んだが、私はまだ混乱している。正しい拡張方法の解像度を確認する方法

まず呼び出しサイト:二つの異なるアセンブリでは、私は2つの異なる名前空間にIOrganziationServiceに拡張メソッドのオーバーロードを定義している

// Assembly: Microsoft.Xrm.Sdk 
void Delete(string entityName, Guid id); 

// 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はこの署名でdeleteメソッドを定義します:

//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 { ... } 

私は私が定義されてきた私の暗黙の事業者からの理解EntityまたはEntityReference

The Call Site service.Delete(id) shows a compiler error: Error CS0121 The call is ambiguous between the following methods or properties: 'Extensions.Delete(IOrganizationService, Entity)' and 'Extensions.Delete(IOrganizationService, EntityReference)'

に変換イドクラスのために定義された暗黙の演算子。私が理解していないのは、DLaB.Xrm名前空間がDLaB.Xrm.Test名前空間よりも近い理由です。なぜなら、私はそれにディレクティブを使用していません。

答えて

1

エリックさんのブログで定義された近の6つのルールがあります。

  1. は最初の派生クラスで宣言された方法は、まず、基本クラスで宣言されたメソッドよりも近くにあります。
  2. ネストされたクラスのメソッドは、それを含むクラスのメソッドよりも近いです。
  3. 受信タイプの方法は、どのような拡張方法よりも近い方法です。
  4. ネストされた名前空間のクラスで見つかった拡張メソッドは、外部の名前空間のクラスで見つかった拡張メソッドよりも近いです。
  5. 現在のネームスペースのクラスで見つかった拡張メソッドは、usingディレクティブで指定された名前空間のクラスにある拡張メソッドよりも近いです。
  6. ディレクティブがネストされた名前空間にある場合にusingディレクティブに記述されている名前空間のクラスで見つかった拡張メソッドが、ディレクティブがあるディレクティブにあるusingディレクティブに記述されている名前空間のクラスにある外部名前空間。

インターフェイスに適用可能なメソッドがないため、最初の3つは適用されません。 4番目が鍵です。 DLaB.Xrmはネストされた名前空間にありますが、別のアセンブリ内にあります。私は、別のクラスからアクセスできるように、拡張メソッドのusingディレクティブをリストしなければならないと誤って信じていました。ネストされた名前空間の拡張メソッドが自動的に利用可能であることが分かりました。

namespace DLaB.Xrm.Testsからnamespace NotNested.DLaB.Xrm.Testsに変更すると、すべての親密度のルールが削除され、あいまいな呼び出しは通常の署名オーバーロードの解決ルールによって解決されます。私が実際に使っていた修正は、Delete呼び出しを一般的なものにすることでした。これは、競合からの2つの暗黙の変換オーバーロードを排除し、呼び出しを自分の優先メソッドに解決できるようにします。

関連する問題