2011-11-14 31 views
0

これは私の状況です。私はコンパイル時に気づいていないタイプのイベントに登録する必要があります。だから、私はこのタイプに動的に加入しようとしています。 EventHandler型のデリゲートを作成するのは、必ずしも正しい型ではないため、これは簡単ではありません。イベントが発生したときにインスタンスメソッドを呼び出す

これはReflection.Emit名前空間への私の最初のダイビングです。私はいくつかの助けが必要です。あなたが見ることができるように

private Delegate CreateDynamicClosedDelegate(Type eventHandlerType) 
{ 
    var handler = new DynamicMethod(string.Empty, null, GetDelegateParameterTypes(eventHandlerType)); 

    ILGenerator ilgen = handler.GetILGenerator(); 

    var onTargetWindowClosedMethodInfo = GetType().GetMethod("OnTargetWindowClosed", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); 

    // this.OnTargetWindowClosed 
    ilgen.Emit(OpCodes.Ldarg_0); 
    ilgen.Emit(OpCodes.Call, onTargetWindowClosedMethodInfo); 
    ilgen.Emit(OpCodes.Pop); 
    ilgen.Emit(OpCodes.Ret); 

    return handler.CreateDelegate(eventHandlerType); 
} 

が、私は(実行時に決定された)特定のイベントタイプのデリゲートを作成しています:これは私がこれまで持っているものです。私はほとんどそこにいると思う、私は "これを得る必要がある。部。

私が正しく理解していれば、ilgen.Emit(OpCodes.Ldarg_0);インスタンスをスタックにロードする必要があります。しかし、それは静的イベントハンドラであるため、最初の引数は送信者であり、送信者はメソッドを含むインスタンスではないと思います。最後に

、私はこのコードを生成しようとしています:イベントへの登録

window.Closed += (sender, e) => this.OnTargetWindowClosed(); 

は(それが簡単です)範囲外であるが、どのように私は、このメソッドを作成することができます。

this.OnTargetWindowClosed(); 

答えて

2

DynamicMethodでスタック上のインスタンスを指定する場合は、別のコンストラクタでオーバーロードを使用する必要があります。所有者のタイプは、インスタンスのタイプです。

public DynamicMethod(string name, Type returnType, Type[] parameterTypes, Type owner); 

デリゲートを作成する際には、このオーバーロードを使用する必要があります。ターゲットパラメータはインスタンスです。あなたのケースでは

public Delegate CreateDelegate(Type delegateType, object target); 

、それは次のようになります。迅速な応答を

public class Dict : Dictionary<int, WindowLogic> 
{ 
    public WindowLogic Get(int key) 
    { 
     return this[key]; 
    } 
} 

public class WindowLogic : IDisposable 
{ 
    static public readonly Dict Instances = new Dict(); 

    static private int s_increment = 0; 

    private int _increment; 

    public WindowLogic() 
    { 
     lock (Instances) 
     { 
      Instances.Add(_increment = ++s_increment, this); 
     } 
    } 

    private Delegate CreateDynamicClosedDelegate(Type eventHandlerType) 
    { 
     var handler = new DynamicMethod(string.Empty, null, GetDelegateParameterTypes(eventHandlerType)); 

     ILGenerator ilgen = handler.GetILGenerator(); 

     var onTargetWindowClosedMethodInfo = GetType().GetMethod("OnTargetWindowClosed", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); 

     // this.OnTargetWindowClosed 
     ilgen.Emit(OpCodes.Ldsfld, typeof(WindowLogic).GetField("Instances", BindingFlags.Static | BindingFlags.Public)); 
     ilgen.Emit(OpCodes.Ldc_I4, _increment); 
     ilgen.Emit(OpCodes.Call, typeof(Dict).GetMethod("Get")); 
     ilgen.Emit(OpCodes.Call, onTargetWindowClosedMethodInfo); 
     ilgen.Emit(OpCodes.Ret); 

     return handler.CreateDelegate(eventHandlerType); 
    } 

    public void OnTargetWindowClosed() 
    { 
     throw new NotImplementedException(); 
    } 

    private Type[] GetDelegateParameterTypes(Type eventHandlerType) 
    { 
     throw new NotImplementedException(); 
    } 

    public void Dispose() 
    { 
     Instances.Remove(_increment); 
    } 
} 
+0

ありがとう:あなたはSilverlightを使用している場合、あなたはこのような何かを行うことができます

private Delegate CreateDynamicClosedDelegate(Type eventHandlerType) { var handler = new DynamicMethod(string.Empty, null, GetDelegateParameterTypes(eventHandlerType), this.GetType()); ILGenerator ilgen = handler.GetILGenerator(); var onTargetWindowClosedMethodInfo = GetType().GetMethod("OnTargetWindowClosed", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); // this.OnTargetWindowClosed ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Call, onTargetWindowClosedMethodInfo); ilgen.Emit(OpCodes.Pop); ilgen.Emit(OpCodes.Ret); return handler.CreateDelegate(eventHandlerType, this); } 

。問題は私がSilverlightを使用していることと、これを使用するときです: var handler = new DynamicMethod(string.Empty、null、GetDelegateParameterTypes(eventHandlerType)、this.GetType()); セキュリティ上重要なメソッドにアクセスするためのセキュリティトランスペアレントメソッド 'MVVMProviders.Logic.WindowLogic.CreateDynamicClosedDelegate(System.Type)'による試み 'System.Reflection.Emit.DynamicMethod..ctor(System.String、System.Type、System.Type [ ]、System.Type) 'が失敗しました。 –

+0

ありがとうございます、魅力のように動作します! –

関連する問題