> 백엔드 개발 > C++ > 범용 FromEvent 메서드를 사용하여 모든 유형의 이벤트를 어떻게 기다릴 수 있습니까?

범용 FromEvent 메서드를 사용하여 모든 유형의 이벤트를 어떻게 기다릴 수 있습니까?

Mary-Kate Olsen
풀어 주다: 2024-12-31 22:38:19
원래의
908명이 탐색했습니다.

How Can I Await Any Event on Any Type Using a General-Purpose FromEvent Method?

범용 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를 생성할 필요가 없습니다. 다양한 종류와 이벤트 방법을 소개합니다.

위 내용은 범용 FromEvent 메서드를 사용하여 모든 유형의 이벤트를 어떻게 기다릴 수 있습니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿