【问题标题】:C# Access instance of generic type argument at runtimeC#在运行时访问泛型类型参数的实例
【发布时间】:2022-07-27 21:37:34
【问题描述】:

我的 Polly IAsyncPolicy 有一个处理异常方法,定义如下:

Handle<ApiException>(ApiException ex)
{
 /// do stuff
} 

ApiException 可以是泛型或非泛型:

public class ApiException

public class ApiException&lt;TResult&gt;

我知道泛型类型的实例将有一个 TResult 类型的名为 Result 的属性,它总是从名为 BaseResponse 的类型继承。

有很多类继承自 BaseResponse。我想避免为它们都编写异常处理程序,并在一个处理程序中完成。

在运行时,我想

a) 确定 ex 是 ApiException 的泛型或非泛型实例,并且

b) 如果实例是通用的,则获取对实例的引用,并访问“结果”属性

我可以通过 ex.GetType().IsGenericType 轻松完成 a)

b) 很麻烦

我试过了:

        if (ex is ApiException<> apiE)
        {

        }

但我需要一个类型才能进入&lt;&gt;

我知道该类型将始终从名为 BaseResponse 的类型继承,所以我尝试了,

        if (ex is ApiException<BaseResponse> apiE)
        {

        }

但它不够具体,并且对于子继承者返回 false,例如 ApiException&lt;AuthResponse&gt; where AuthResponse : BaseResponse

有什么可以做的吗?

【问题讨论】:

  • 为什么没有两种方法,一种用于泛型,一种用于非泛型?
  • 你打算对结果属性做什么?您没有任何编译时类型,因此您在处理它方面非常有限,而不仅仅是使用更多反射或“动态”。总体而言,泛型在“运行时”方面表现不佳。
  • @TimSchmelter 因为 TResult 可能有很多类型,所以我需要很多方法。我只需要访问所有 TResult 都将继承自的基础 TBaseResult 上的属性
  • @JonasH 对我来说,在方法上设置编译时约束是很棘手的,因为 ApiException 和 ApiException 是由没有任何编译时间约束的工具(NSwag)生成的。也许那里有线索,也许我可以摆弄 NSwag 设置来实现编译时间限制。我打算访问在其父 TBaseResult 上定义的 TResult 上的属性

标签: c# .net generics polly


【解决方案1】:

您确实可以获取泛型参数的类型,您也可以使用反射读取Result。您是否可以用它做任何有意义的事情取决于。

static void Handle<T>(T ex) where T : ApiException
{
    var type = typeof(T);
    if(!type.IsGenericType)
    {
        Console.WriteLine($"{type} is non generic");
    }
    else
    {
        var gType = type.GetGenericArguments()[0];
        Console.WriteLine($"{type} is generic, the type is {gType}");
        
        var result = type.GetProperty("Result");
        var obj = result.GetValue(ex);
        Console.WriteLine($"Got Result={obj}");
    }
        
}

现场示例:https://dotnetfiddle.net/DpyZpk

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-10
    • 2016-05-11
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 2017-06-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多