有没有办法在C#中简化这个reflection代理代码?

在这个响应中,我提出了以下帮助方法,可以由不同的Task创建者重用,以将事件转换为任务完成源。

 // Helper method static Task TaskFromEventHelper(object target, string eventName, Func<TaskCompletionSource, object> resultSetterFactory) { var tcs = new TaskCompletionSource(); var addMethod = target.GetType().GetEvent(eventName).GetAddMethod(); var delegateType = addMethod.GetParameters()[0].ParameterType; var d = Delegate.CreateDelegate(delegateType, resultSetterFactory(tcs), "Invoke"); addMethod.Invoke(target, new object[] {d}); return tcs.Task; } // Empty events (Action style) static Task TaskFromEvent(object target, string eventName) { return TaskFromEventHelper(target, eventName, (Func<TaskCompletionSource, object>)(tcs => (Action)(() => tcs.SetResult(null)))); } // One-value events (Action style) static Task TaskFromEvent(object target, string eventName) { return TaskFromEventHelper(target, eventName, (Func<TaskCompletionSource, object>)(tcs => (Action)(tcs.SetResult))); } // Two-value events (Action or EventHandler style) static Task<Tuple> TaskFromEvent(object target, string eventName) { return TaskFromEventHelper(target, eventName, (Func<TaskCompletionSource<Tuple>, object>)(tcs => (Action)((t1, t2) => tcs.SetResult(Tuple.Create(t1, t2))))); } 

在我给出的三个例子的每一个中都使用了helper方法,有一个tcs.SetResult组件,这让我觉得有一种方法可以将它移动到helper方法,这可能会简化签名,所以也许是帮助方法只需接受一个Func ,其中Func将获取event的输出并将其转换为tcs.SetResult所需的任何tcs.SetResult

即,我认为必须有一种方法来创建一个助手,所以我可以写它

 // Empty events (Action style) static Task TaskFromEvent(object target, string eventName) { return TaskFromEventHelper(target, eventName, new Func(() => null)); } // One-value events (Action style) static Task TaskFromEvent(object target, string eventName) { return TaskFromEventHelper(target, eventName, new Func(t => t)); } // Two-value events (Action or EventHandler style) static Task<Tuple> TaskFromEvent(object target, string eventName) { return TaskFromEventHelper<Tuple>(target, eventName, new Func<T1, T2, Tuple>(Tuple.Create)); } 

,但那就是我不知道的原因?Func上面。 这个例如需要?两个参数。 它可以以某种方式作为object传递吗? 我觉得它有可能,但如果是这样,它需要一些真实的reflection魔法。

你可以使用Expression

 static Task TaskFromEventHelper(object target, string eventName, Delegate resultSetter) { var tcs = new TaskCompletionSource(); var addMethod = target.GetType().GetEvent(eventName).GetAddMethod(); var delegateType = addMethod.GetParameters()[0].ParameterType; var methodInfo = delegateType.GetMethod("Invoke"); var parameters = methodInfo.GetParameters() .Select(a => Expression.Parameter(a.ParameterType)) .ToArray(); // building method, which argument count and // their types are not known at compile time var exp = // (%arguments%) => tcs.SetResult(resultSetter.Invoke(%arguments%)) Expression.Lambda( delegateType, Expression.Call( Expression.Constant(tcs), tcs.GetType().GetMethod("SetResult"), Expression.Call( Expression.Constant(resultSetter), resultSetter.GetType().GetMethod("Invoke"), parameters)), parameters); addMethod.Invoke(target, new object[] { exp.Compile() }); return tcs.Task; }