【问题标题】:How to reflect types that have an interface of generic, and get that type of generic如何反映具有泛型接口的类型,并获取该泛型类型
【发布时间】:2010-02-21 02:59:13
【问题描述】:

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

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

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

我不能假设类的结构、它的接口(如果有的话)或类似的。我唯一知道我的目标是 ExportableAs&lt;T&gt; 从用于创建此插件的共享程序集中。但是,我需要动态注册类型。

所以,我使用通用接口来标记要导出的类型。在这种情况下,它是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
            })
        );

这是有效的,但请注意上面的评论“这是不正确的”。该类型是UserService的派生类。

我需要的最终结果是:

  • 泛型类型传入IExportableAs&lt;T&gt;(在本例中为IUserService)
  • 派生类类型(在本例中为UserService)

这个问题得到了很好的支持,因为它让我很接近(如您在上面看到的):How to determine if a type implements a specific generic interface type 但是,我需要更进一步来找到该泛型类型。

请随意破坏我上面的 linq。

提前致谢!

【问题讨论】:

    标签: linq generics types


    【解决方案1】:

    知道了

    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 Framework 在那里特别聪明。现在更正了代码,我知道它不是。

    【讨论】:

    • 有趣。使用匿名类型创建对象。这有希望。 +1
    • 是的,就是这样。但请注意,您正在 Select() 子句中创建第二个匿名类型。它应该是:.Select(ti =&gt; new ComposablePart() { Name = ti.t.FullName, Type = ti.i.GetGenericArguments()[0] }); 否则,它不会转换为 ToList() 上的已知类型。
    • 我对@9​​87654323@ 索引有些担心。这将我限制为只有 1 个 IExportableAs&lt;&gt; 对吗?
    • 抱歉错误;我懒得在我的测​​试应用程序中定义 ComposablePart :)。我会解决的。没有GetGenericTypeDefinition()[0] - 有一个GetGenericArguments()[0] 将您限制为每个泛型类型IExportableAs 中的一个类型T。如果您需要更多,可以轻松扩展,但这没有意义。您可以在一个类上拥有任意数量的 IExportableAs。
    • 澄清一下:i.GetGenericTypeDefinition() 只是将IExportableAs&lt;T&gt; 转换为IExportableAs&lt;&gt; 以便进行比较。
    猜你喜欢
    • 2021-01-25
    • 2019-07-21
    • 1970-01-01
    • 2019-12-06
    • 1970-01-01
    • 1970-01-01
    • 2014-07-31
    • 2014-05-07
    • 1970-01-01
    相关资源
    最近更新 更多