범용 FromEvent 메서드
원래 FromEvent 메서드에서는 기다리고 싶은 각 이벤트와 클래스에 대해 별도의 메서드를 만들어야 합니다. 상용구 코드를 제거하기 위해 개발자는 보다 범용적인 솔루션을 모색했습니다.
한 가지 접근 방식은 리플렉션을 사용하여 이벤트와 해당 대리자 유형을 검색하는 것입니다. 그러나 대리자의 매개변수에 액세스하고 TaskCompletionSource를 수정하면 문제가 발생했습니다.
사용자 지정 솔루션
다음은 IL 방출 및 이벤트 처리기를 활용하는 사용자 지정 솔루션입니다.
public static class ExtensionMethods { public static Task<object[]> FromEvent<T>(this T obj, string eventName) { // Create a TaskCompletionSourceHolder to manage the TaskCompletionSource and event handler var tcsh = new TaskCompletionSourceHolder(); // Get the event and its delegate type EventInfo eventInfo = obj.GetType().GetEvent(eventName); Type eventDelegateType = eventInfo.EventHandlerType; // Create a dynamic method to handle the event DynamicMethod handler = CreateEventHandler(eventDelegateType); // Add the event handler to the target object eventInfo.AddEventHandler(obj, handler.CreateDelegate(eventDelegateType, tcsh)); // Return the Task from the TaskCompletionSourceHolder return tcsh.Task; } private static DynamicMethod CreateEventHandler(Type eventDelegateType) { // Get the parameter types of the event delegate var parameterTypes = GetDelegateParameterTypes(eventDelegateType); // Insert the TaskCompletionSourceHolder as the first parameter parameterTypes.Insert(0, typeof(TaskCompletionSourceHolder)); // Create a new dynamic method and IL generator DynamicMethod handler = new DynamicMethod("EventHandler", typeof(void), parameterTypes, true); ILGenerator ilgen = handler.GetILGenerator(); // Load the TaskCompletionSourceHolder and create an array to store the arguments ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldc_I4, parameterTypes.Count - 1); ilgen.Emit(OpCodes.Newarr, typeof(object)); // Store each argument in the array for (int i = 1; i < parameterTypes.Count; i++) { ilgen.Emit(OpCodes.Ldloc_0); ilgen.Emit(OpCodes.Ldc_I4, i - 1); ilgen.Emit(OpCodes.Ldarg, i); ilgen.Emit(OpCodes.Stelem_Ref); } // Call the SetResult method on the TaskCompletionSourceHolder ilgen.Emit(OpCodes.Call, typeof(TaskCompletionSourceHolder).GetMethod("SetResult")); // Return from the method ilgen.Emit(OpCodes.Ret); return handler; } private static List<Type> GetDelegateParameterTypes(Type delegateType) { var parameters = delegateType.GetMethod("Invoke").GetParameters(); var parameterTypes = parameters.Select(p => p.ParameterType).ToList(); return parameterTypes; } }
이 방법을 사용하면 이제 모든 이벤트를 기다릴 수 있습니다. 유형:
await new MyClass().FromEvent("MyEvent");
이 솔루션의 이점
위 내용은 범용 FromEvent 메서드를 사용하여 모든 유형의 이벤트를 어떻게 기다릴 수 있습니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!