10

次の問題があります: .NET 4.5、Windows Phone 8、および Windows 8 ストア アプリを対象とするポータブル クラス ライブラリ内から呼び出したいのですDelegate.CreateDelegateが、コードがコンパイルされません。コンパイラは、型のメソッドが見つからないと言いますDelegate

おもしろいことに、たとえば Microsoft の PRISM ライブラリは、Portable Class Library から「Delegate.CreateDelegate」を呼び出すことができます。それはDelegateReferenceクラスで行います。PRISM ポータブル クラス ライブラリは、.NET 4.0、Windows 8 ストア アプリ、Windows Phone 8、および Silverlight 5 (したがって、より制限的なセット) を対象としています。

コンパイルされないコードは次のようになります。

public class MyClass
{
    public void MyMethod<T>(EventHandler handler)
    {
        var @delegate = Delegate.CreateDelegate(typeof (OpenEventHandler<T>), null, handler.GetMethodInfo());
    }
}

public delegate void OpenEventHandler<in T>(T target, object sender, EventArgs arguments);

例はここからダウンロードできます: https://dl.dropboxusercontent.com/u/14810011/PortableClassLibraryReferenceProblem.zip

DelegateReferenceこれには、私のライブラリ プロジェクトと、クラスとそのインターフェイスのみを含む PRISM PubSubEvents プロジェクトの非常に簡素化されたバージョンが含まれています。後者の完全なソース コードは、http: //prismwindowsruntime.codeplex.com/SourceControl/latestにあります。

Delegateすべてのメンバーを使用するにはどうすればよいですか? よろしくお願いします。

Henk Holtermanの答えの後に編集:

GetMethodInfo() は、PCL サブセットでサポートされている拡張メソッドです。Delegate.CreateDelegateとにかく、それは、PRISM の PCL プロジェクトでは呼び出せるのに、私が呼び出せないという問題とは関係ありません。

コンパイルされないコードの画像

Hans Passantsのコメントの後のEDIT 2 :

いろいろ試してみたところ、Silverlight 5 をポータブル ライブラリのターゲットとして有効にすると、実際にアクセスできることがわかりましたDelegate.CreateDelegate(そして、GetMethodInfo 拡張メソッドはアクセスできなくなりました)。Delegate.CreateDelegate内部で Windows 8 ストアおよび電話アプリ用の別の API にマップされている可能性がありますか? Silverlight 5 を有効なターゲットとして追加したという理由だけで、このメソッドが突然アクセス可能になると考えることができる唯一の方法です。

(これを再現するには、「MyPortableClassLibrary」プロジェクトを右クリックし、「プロパティ」をクリックし、「ライブラリ」タブで変更をクリックして、ポータブル ライブラリの対象となるフレームワークを選択します。)

また、本日、Windows ストア アプリ プロジェクトを作成したところ、.NET のクラスに Windows ランタイム用のCreateDelegateメソッドが定義されていないことがわかりました。Delegate

私の実際のプロジェクトでは、Silverlight 5 をターゲットにしたくありません。Rx を使用IObservable<T>IObserver<T>ており、これらのインターフェイスが Silverlight で定義されていないためです。

4

2 に答える 2

13

OK、一晩寝た後、私の質問は実際には「Windows ランタイムで導入された新しい API でデリゲートを動的に作成するにはどうすればよいですか?」であることに気付きました。. Rafael が私の質問のコメントで示したように、.NET に加えて Windows 8 / Phone 8 がターゲットにされた場合、異なる API が提供されます。Silverlight もターゲットにすると、Windows 8 / Phone 8 で使用できない API がマップされます。このためDelegate.CreateDelegate、Silverlight をポータブル クラス ライブラリのターゲットとして追加すると、突然呼び出すことができるようになります。.NET では、Reflection 用の新しい API が .NET 4.5 で導入されました。

とにかく、Windows 8 / Windows Phone 8 でデリゲートを作成するには、次のMethodInfo.CreateDelegateようにメソッドを使用する必要があります。

public class MyClass
{
    public void MyMethod<T>(EventHandler handler)
    {
        var methodInfo = handler.GetMethodInfo();
        var @delegate = methodInfo.CreateDelegate(typeof(OpenEventHandler<T>), null);
    }
}

public delegate void OpenEventHandler<in T>(T target, object sender, EventArgs arguments);
于 2013-08-12T10:49:28.850 に答える
10

Silverlight を追加/削除するときに表示されるのは、2 つの異なる .NET API サーフェス エリア間のポータブル フリップです。ここでは、これら 2 つの異なる領域について説明します。.NET ポータブル サブセット (レガシー) とは何ですか? .

従来の表面領域と呼ばれるものでは、このメソッドは Delegate に存在します。新しい表面領域では、このメソッドは MethodInfo に移動されました。

なぜ私たちはこれをしたのですか?

レイヤリングの理由で。新しいサーフェスでは、リフレクション タイプ (つまり、Assembly、MemberInfo、MethodInfo など) は、Delegate を含むコア プリミティブよりも上位のレイヤーにあると見なされます。従来の表面領域 (mscorlib にすべて存在する) とは異なり、これらの型は異なるアセンブリにあります。それぞれ、System.Reflection.dll と System.Runtime.dll。

このメソッド (他のいくつか) は、下位層 (System.Runtime.dll) の何かを上位層 (System.Reflection.dll) の何かに依存させていました。それを防ぐために、依存関係が逆になりました。

于 2013-08-14T20:58:50.693 に答える