获取所有使用特定通用calsses实现类的类

时间:2015-05-08 17:08:24

标签: c# generics

我想在我的程序中找到实现具有特定调用的给定类作为泛型类型的所有类。 在下面的示例中,我希望找到在这种情况下实现MyBaseClass<MyScraper, MyElance>的所有类,它将是MyProperty而不是OtherProperty,因为它实现了其他泛型类。 怎么办呢?

public class MyProperty : MyBaseClass<MyScraper, MyElance>
{
    public override string test()
    {
        var test = base.test();
        test += " + the new";
        return test;
    }
}
public class OtherProperty : MyBaseClass<OtherScraper, OtherElance>
{
    public override string test()
    {
        var test = base.test();
        test += " + the other";
        return test;
    }
}

public class MyBaseClass<S, E>
    where S : IScraper
    where E : IElance
{
    public virtual string test()
    {
        return "base";
    }
}

编辑: 找到了解决方案,但请告诉我是否有更好的方法

    var test = from x in Assembly.GetAssembly(typeof(Program)).GetTypes()
                                let y = x.BaseType
                                where !x.IsAbstract && !x.IsInterface &&
                                y != null && y.IsGenericType &&
                                y.GetGenericTypeDefinition() == typeof(MyBaseClass<,>) &&
                                y.GenericTypeArguments[0] == typeof(MyScraper) &&
                                y.GenericTypeArguments[1] == typeof(MyElance)
                                select x;

最终解决方案:

   var types = AppDomain.CurrentDomain.GetAssemblies()
        .SelectMany(a => a.GetTypes())
        .Where(x => !x.IsAbstract && !x.IsInterface)
        .Where(x => x.BaseType != null &&
                    x.BaseType.IsGenericType &&
                    x.BaseType.GetGenericTypeDefinition() == typeof (MyBaseClass<,>) &&
                    x.BaseType.GenericTypeArguments[0] == typeof (MyScraper) &&
                    x.BaseType.GenericTypeArguments[1] == typeof (MyElance))
        .Select(x => x).ToList();

3 个答案:

答案 0 :(得分:1)

试试这个:

//var desiredImplementation = typeof (MyBaseClass<>).MakeGenericType(typeof (MyScraper), typeof (MyElance));

var desiredImplementation = typeof (MyBaseClass<MyScraper, MyElance>);

var implementingTypes = Assembly
        .GetExecutingAssembly()
        .GetExportedTypes()
        .Where(type => desiredImplementation.IsAssignableFrom(type))
        .ToList();

您可以将GetExportedTypes()替换为GetTypes()BindingFlags,以进一步内省程序集。

答案 1 :(得分:1)

装配扫描几乎是最好的方法。

除了你的algorythm,我建议扫描AppDomain而不是特定的程序集 - 这将允许你(或其他人!)更容易扩展你的图书馆......

AppDomain.CurrentDomain.GetAssemblies()
    .SelectMany(a => a.GetTypes())
    //...

(免责声明请原谅Linq使用此处,但我厌恶语法linq)

此外,请确保已加载任何其他装配,以确保您在扫描时不会遗漏任何内容。

答案 2 :(得分:1)

var searchType = typeof(MyBaseClass<MyScraper, MyElance>);
            var types =
                AppDomain.CurrentDomain.GetAssemblies()
                    // For search only on assemblies where could exsist this types
                    .Where(a => a.GetName().Name == searchType.Assembly.GetName().Name || a.GetReferencedAssemblies().Any(n => n.Name == searchType.Assembly.GetName().Name))
                    .Where(t => !t.IsAbstract && !t.IsInterface)
                    .Select(t => t.GetTypes().Where(a => searchType.IsAssignableFrom(a)))
                    .SelectMany(a => a);

我使用此版本来搜索所有已加载的程序集,并使用其他过滤器来处理不能包含我的类型的程序集