反映异步方法的返回类型

问题描述 投票:0回答:2

下面是我希望用于实现缓存提供程序的拦截器的代码。我需要确定将调用的方法的返回类型。当调用的方法是同步时,这非常简单。然而,我遇到的大多数方法都是异步的,它们返回一个任务。

如何使用反射来确定异步方法的返回类型?

public void Intercept(IInvocation invocation)
{
    try
    {
        if (invocation.Method.Name.StartsWith("Retrieve"))
        {
            var returnType = invocation.Method.ReturnType;
            if (returnType.IsGenericType &&
                returnType.GetGenericTypeDefinition() == typeof (Task<>))
            {
                var returnTypeOfTheTask = returnType.NeedSomeHelpHere();
            }
        }
        _circuitBreaker.Execute(invocation);
    }
    // ...
}
c# reflection aop castle-dynamicproxy
2个回答
4
投票

您可以使用其中一个

var returnTypeOfTheTask = returnType.GetGenericArguments()[0];

var returnTypeOfTheTask = returnType.GenericTypeArguments[0];

您将使用哪个主要取决于您需要支持的平台(例如,第一个选项自 .NET 2.0 以来就存在,但在 Modern UI 中不受支持,而第二个选项在 .NET 4.0 中不存在)。如果两种方法都能满足您的需求,我建议使用第二种方法。


0
投票

根据上面学到的知识,我创建了一个方法,可以一直深入到类型层次结构中,直到找到不再通用的类型。

    /// <summary>
    /// Get the output type of the given method.
    /// 1. Get the method info using reflection.
    /// 2. Check if the method is an async method by calling the `IsAwait()` method.
    /// 3. If the method is an async method, get the return type using the `ReturnType` property.
    ///     a. Check if the return type is a generic type by calling the `IsGenericType` property.
    ///     b. If the return type is a generic type, get the generic arguments using the `GetGenericArguments` method.
    ///     c. Continue repeating #3 until the return type is no longer Generic.
    /// 4. If the method is not async then get the return type using the `ReturnType` property.
    /// </summary>
    /// <param name="runType"></param>
    /// <param name="methodName"></param>
    /// <param name="methodParameterFQNs"></param>
    /// <returns></returns>
    public static Type GetOutputType(
        Type runType,
        string methodName,
        List<string> methodParameterFQNs)
    {
        Type result = null;

        MethodInfo methodInfo =
            GetMethodByParameterMatch(
                runType, methodName, methodParameterFQNs);

        if (methodInfo.IsAwait())
        {
            result = methodInfo.ReturnType;

            if (result.IsGenericType)
            {
                while (result.IsGenericType)
                {
                    Type[] genericArguments = result.GetGenericArguments();

                    if (genericArguments.Length > 0)
                    {
                        result = genericArguments[0];
                    }
                }
            }
            else
            {
                result = methodInfo.ReturnType;
            }
        }
        else
        {
            result = methodInfo.ReturnType;
        }

        return result;
    }
© www.soinside.com 2019 - 2024. All rights reserved.