如何反映具有通用接口的类型,并获取通用类型

5

我的第一个目标是基于特定接口过滤具有泛型的类型。

我的第二个目标是获取泛型参数本身的类型。

public UserService : IUserService, IDisposable, IExportableAs<IUserService>
{
  ...
}

我无法假设类的结构、接口(如果有的话)或类似内容。唯一我知道的是,我正在从用于创建此插件的共享程序集中针对ExportableAs<T>进行目标定位。但是,我需要动态注册类型。
因此,我使用通用接口来标记要导出的类型。在这种情况下,它是IUserService。我这样做是假设一些巧妙的Linq查询可以给我想要的结果。但是,我遇到了一些小问题。
以下是我目前的代码:
assembly.GetTypes()
    .Where(t => t.GetInterfaces().Any(i => 
                i.IsGenericType &&
                i.GetGenericTypeDefinition() == typeof(IExportableAs<>))
            ).ToList()
    .ForEach(t => _catalogs.Add(
            new ComposablePart()
            {
                Name = t.FullName,
                Type = t // This is incorrect
            })
        );

这段代码是正确的,但请注意上面的注释"This is incorrect"。这个类是UserService的派生类。
我的最终目标是:
  • 将泛型类型传递到IExportableAs<T>中(在本例中为IUserService
  • 派生类类型(在本例中为UserService
这个问题得到了很多赞,因为它让我接近了答案(如上所示):How to determine if a type implements a specific generic interface type,但是我需要更进一步找到那个泛型类型。
如果你觉得我的LINQ有问题,可以随意修改。
提前感谢您!
1个回答

4

明白了

assembly.GetTypes().SelectMany(t => t.GetInterfaces(), (t, i) => new { t, i })
    .Where(ti => ti.i.IsGenericType &&
                 ti.i.GetGenericTypeDefinition() == (typeof(IExportableAs<>)))
    .Select(ti => new ComposablePart() {
        Name = ti.t.FullName,
        Type = ti.i.GetGenericArguments()[0]
    });

[编辑] 在我兴奋的时候,我没有让我的测试程序运行足够长的时间来在接口上抛出一个不是泛型的异常。我以为.NET框架已经特别聪明了。现在我知道它不是这样的,所以我纠正了代码。


有趣。使用匿名类型创建对象。这很有前途。+1 - eduncan911
是的,就是这样。不过请注意,在Select()子句中你正在创建第二个匿名类型。应该是:.Select(ti => new ComposablePart() { Name = ti.t.FullName, Type = ti.i.GetGenericArguments()[0] });否则,在ToList()时它将无法转换为已知类型。 - eduncan911
我对GetGenericTypeDefinition()[0]的索引有所担忧。这会限制我只能正确使用1个 IExportableAs<>,是吗? - eduncan911
抱歉出现错误;我懒得在我的测试应用程序中定义 ComposablePart :)。我会修复的。没有 GetGenericTypeDefinition()[0] - 只有一个 GetGenericArguments()[0],它将你限制在每个泛型类型 IExportableAs<T> 中只能使用一种类型 T。如果需要更多,可以轻松扩展,但这没有意义。您可以在类上拥有任意数量的 IExportableAs<T>。 - pdr
只是为了澄清:i.GetGenericTypeDefinition()IExportableAs<T> 简单转换成 IExportableAs<>,以便进行比较。 - pdr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接