gpt4 book ai didi

c# - 有没有办法在 C# 中简化这个反射委托(delegate)代码?

转载 作者:行者123 更新时间:2023-11-30 16:21:53 27 4
gpt4 key购买 nike

this作为回应,我想出了以下辅助方法,可以被不同的 Task 重复使用。创建者将事件转换为任务完成源。

// Helper method
static Task<T> TaskFromEventHelper<T>(object target, string eventName, Func<TaskCompletionSource<T>, object> resultSetterFactory) {
var tcs = new TaskCompletionSource<T>();
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>, object>)(tcs => (Action)(() => tcs.SetResult(null))));
}

// One-value events (Action<T> style)
static Task<T> TaskFromEvent<T>(object target, string eventName) {
return TaskFromEventHelper(target, eventName, (Func<TaskCompletionSource<T>, object>)(tcs => (Action<T>)(tcs.SetResult)));
}

// Two-value events (Action<T1, T2> or EventHandler style)
static Task<Tuple<T1, T2>> TaskFromEvent<T1, T2>(object target, string eventName) {
return TaskFromEventHelper(target, eventName, (Func<TaskCompletionSource<Tuple<T1, T2>>, object>)(tcs => (Action<T1, T2>)((t1, t2) => tcs.SetResult(Tuple.Create(t1, t2)))));
}

在我给出的三个使用辅助方法的示例中,每个示例中都有一个 tcs.SetResult。组件,这让我觉得还有一种方法可以将其移至辅助方法,这可能会简化签名,因此辅助方法可能只需要接受 Func<?, T>。 ,哪里Func将采用 event 的输出并将其转换为任何 tcs.SetResult需要。

也就是说,我想一定有一种方法可以创建一个助手,这样我就可以把它写成

// Empty events (Action style)
static Task TaskFromEvent(object target, string eventName) {
return TaskFromEventHelper<object>(target, eventName, new Func<object>(() => null));
}

// One-value events (Action<T> style)
static Task<T> TaskFromEvent<T>(object target, string eventName) {
return TaskFromEventHelper<T>(target, eventName, new Func<T, T>(t => t));
}

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

,但这就是我不知道 ? 的原因在Func<?, T>多于。例如,这个需要 ?两个参数。可以传入object吗?不知何故?我觉得这是可能的,但如果是这样,它需要一些真正的反射魔法。

最佳答案

您可以使用表达式:

static Task<T> TaskFromEventHelper<T>(object target, string eventName, Delegate resultSetter)
{
var tcs = new TaskCompletionSource<T>();
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;
}

关于c# - 有没有办法在 C# 中简化这个反射委托(delegate)代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12885459/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com