これで、私はしばらくの間、この問題を解決しました。実行時に生成された不明な型のイベントハンドラ
状況:
Iが変化することができるactivator.CreateInstance(X)
X型を用いて、タイプXのオブジェクトをインスタンス化するが、常に同じプロパティとメソッドを有します。 問題は、タイプxはReadCompleted(これはデリゲート)のイベントReadCompletedを持ち、タイプyは同じデリゲートで同じイベントを持ちますが、ReadCompleted1、z => ReadCompleted2などのタイプです。
ソリューション: は、私は、次のコードを使用して、実行時にデリゲートを割り当てます。
Dim Client As Object = ServiceProvider.GetService(TypeDict(Entity))
Dim TaskCompletionSource As New TaskCompletionSource(Of Entity)()
Dim addMethod As MethodInfo = Client.GetType().GetMethod("add_ReadCompleted")
Dim removeMethod As MethodInfo = Client.GetType().GetMethod("remove_ReadCompleted")
Dim self As Object = Nothing
Dim getSelf As Func(Of Object) = Function() self
Dim eventArgType As Type = Client.GetType().GetEvent("ReadCompleted").EventHandlerType.GetMethod("Invoke").GetParameters()(1).ParameterType
Dim e As ParameterExpression = Expression.Variable(eventArgType)
Dim ExpBlock As BlockExpression = Expression.Block({Expression.Parameter(GetType(Object)), e},
Expression.Call(
Nothing,
Me.GetType().GetMethod("ProcessTask"),
Expression.Convert(e, eventArgType),
Expression.Constant(TaskCompletionSource)),
Expression.Call(
Expression.Constant(Client),
removeMethod,
Expression.Convert(
Expression.Invoke(
Expression.Constant(getSelf)),
addMethod.GetParameters()(0).ParameterType)
)
)
Dim lambda As LambdaExpression = Expression.Lambda(
addMethod.GetParameters()(0).ParameterType,
ExpBlock,
Expression.Parameter(GetType(Object)),
Expression.Parameter(eventArgType))
Dim dlg As [Delegate] = lambda.Compile()
self = dlg
addMethod.Invoke(Client, {dlg})
Client.ReadAsync(PrimaryKey)
今私のLINQの知識と、それはExpressionクラスが限られていると私は、MSDNのドキュメントを検索するには、私のベストを尽くしたが、私はそれを理解できないのですout:
メソッドProcessTaskが正しく呼び出されます。私のパラメータeは常にNothingなので、NullReferenceExceptionが発生します。 方法:
Public Shared Sub ProcessTask(ByVal e, ByRef tcs)
'Console.WriteLine(e.GetType())
If e.Error IsNot Nothing Then
tcs.TrySetException(e.Error)
ElseIf e.Cancelled Then
tcs.TrySetCanceled()
Else
tcs.TrySetResult(e.Result)
End If
End Sub
は、私は私はこれが私のメソッドを呼び出すための正しい方法ですが、明らかにそれはないそれを見る方法によると、理由はわかりません。誰かがこれに対して正しい方向に向けることができますか? 私はまったく目立たず、何か非常に明白なものがありませんでした....
ありがとうございます!
EDIT:オブジェクトパラメータとして
Dim s As ParameterExpression = Expression.Variable(GetType(Object), "Sender")
Dim ExpBlock As BlockExpression = Expression.Block({s, e},
Expression.Call(
Nothing,
GetType(Console).GetMethod("WriteLine", New Type() {GetType(String)}),
Expression.Call(s, GetType(Object).GetMethod("ToString"))),
Expression.Call(
Expression.Constant(Client),
removeMethod,
Expression.Convert(
Expression.Invoke(
Expression.Constant(getSelf)),
addMethod.GetParameters()(0).ParameterType)
))
送信者も何もありませんので、私: 私はいくつかのより多くのデバッグを実行しようとしました答えを待っている間は(このシナリオでは地獄である)私がしなければことを見ました私の議論のどれも通過していないと感じている...
これは、問題についてより多くの光を出すのに役立ちます。 )((エンティティの)新TaskCompletionSourceなどのオブジェクト= ServiceProvider.GetService(TypeDict(エンティティ)) 点心TaskCompletionSourceとして
薄暗いクライアント:
もし私がそれを見逃しているのかどうかは分かりませんが、実際には明らかですが、どこで 'ProcessTask'を呼び出していますか? – David
こんにちは@David、見ていただきありがとうございます。 ProcessTaskの呼び出しは、式 'Expression.Call( Nothing、 Me.GetType()。GetMethod(" ProcessTask ")、 の式の内部にあります。 少なくとも、それは私がそれがしていると思う、または少なくともそれが何をすると思われるかです... この式は、実際にはReadCompletedイベントのハンドラです。クライアント。 –
また、私はProcessTaskメソッドがReadCompletedEventでトリガされることを知っています、それはちょうど動的なeventargsを渡していないか、それがnullのような結果になるか変換しません... –