単体テストでは、実際のハンドラーに転送する前にテスト コードを挿入できるように、イベントを動的にラップしようとしています。これは私が今持っているものです:
Delegate handler = // the original method handler
object myObject = // the original object
EventInfo ei = myObject.GetType().GetEvent("MyEvent");
Delegate d = GenerateWrappedDelegate(ei);
ei.AddEventHandler(myObject, d);
...
private GenerateWrappedDelegate(EventInfo eventInfo)
{
var eventHandlerType = eventInfo.EventHandlerType;
int arity = eventHandlerType.GetMethod("Invoke").GetParameters().Count();
var methodName = string.Format("Arity{0}", arity);
var eventRegisterMethod = typeof(EventMonitor).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);
return Delegate.CreateDelegate(eventHandlerType, this, eventRegisterMethod);
}
private void Arity1(object arg1)
{
Handle(() => handler.DynamicInvoke(arg1));
}
private void Arity2(object arg1, object arg2)
{
Handle(() => handler.DynamicInvoke(arg1, arg2));
}
private void Handle(Action action)
{
// Do something interesting here, before the original event handler is called
action();
}
Arity
イベントが持つパラメーターの数が事前にわからないため、これらのメソッドはかなりたくさんありますが、それらすべてを元のデリゲートに渡したいと考えています。
イベント ハンドラー デリゲートが次のようになっている場合、これはすべて正常に機能します。
public delegate void MyDelegate(object sender, EventArgs e);
public event MyDelegate MyEvent;
ただし、コード ベースの一部のデリゲートは、「従来の」イベント ハンドラーのようには見えませんが、次のようなものです。
public delegate void MyOtherDelegate(object sender, int updatedValue);
public event MyOtherDelegate MyOtherEvent;
そして、コードが突然機能しなくなりました。で失敗しますint
。
次のように、複雑if
なステートメントGenerateWrappedDelegate
を追加してArity
メソッドを追加することで、この問題を回避しました。
private void Arity2oo(object arg1, object arg2)
{
Handle(() => handler.DynamicInvoke(arg1, arg2));
}
private void Arity2oi(object arg1, int arg2)
{
Handle(() => handler.DynamicInvoke(arg1, arg2));
}
しかし、それは明らかにうまくスケーリングできず、非常に冗長です。
hereで説明されているように、動的メソッドの生成を検討してきましたが、これによりさらに混乱します。私は MSIL に詳しくありません。また、実行時の型に基づいてすべてのパラメーターを読み込むメソッド本体を生成し、DynamicInvoke
それぞれを呼び出す方法も知りません。見た目は美しくないと思います。
私たちは.NET 4.0を使用しているので、私も調べてdynamic
いますが、それを機能させる方法もわかりません。
私はアイデアがありません。あなたがいずれかを持っている?