好的,所以我一直堅持這一段時間,結合了來自這裏的各種問題解決方案。未知類型的運行時生成的EventHandler
情況:
我通過使用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和知識,這是表達類是有限的,我盡我所能去研究的MSDN文檔,但我想不出它out:
ProcessTask被調用的方法正確,爲此我wo足夠長的時間,但我的參數e總是沒有,導致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
我不知道爲什麼,根據我怎麼看它這個是叫我的方法正確的方法,但顯然事實並非如此。有人能爲我指出正確的方向嗎? 可能是我只是普通的盲人,失去了非常明顯的東西....
在此先感謝!
編輯: 雖然等待一個答案,我試圖做一些更多的調試(這是地獄在這種情況下)看到,如果我這樣做:
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)
))
發送者爲對象的參數也不算什麼,所以我我的感覺是我的論點都沒有通過...
希望這有助於闡明這件事。
不知道如果我只是想念它,它實際上很明顯,但是,你在哪裏調用'ProcessTask'? – David
嗨@David,謝謝你看看。 對ProcessTask的調用在以下表達式內: 'Expression.Call( Nothing, Me.GetType()。GetMethod(「ProcessTask」), 表達式。轉換(e,eventArgType), Expression.Constant(TaskCompletionSource))' 至少這就是我認爲它的作用,或者至少它應該做什麼...... 該表達式實際上是ReadCompleted事件的處理程序客戶端。 –
此外,我知道在ReadCompletedEvent上觸發ProcessTask方法,它只是以某種方式不傳遞動態事件列表,或者沒有將其轉換爲正確的結果爲null或類似的東西......對於後者我無能爲力...... –