この応答で、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)))));
}
ヘルパーメソッドを使用する3つの例のそれぞれに、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>
。たとえば、これは 2つのパラメータである必要?
があります。どういうわけか受け継がれるのでしょうか?それは可能だと思いますが、もしそうなら、本当の反射魔法が必要です。object