实例化实现特定接口的所有类

Tom*_*han 17 c# reflection

我有一个接口IExample和一组类ClassOne,ClassTwo并且ClassThree都在不同的命名空间中定义.我可能会删除其中一个类,或者在开发的后期阶段在新的位置添加一个新类.

现在,我想找到IExample在运行时实现的所有类型,并实例化它们.(我事先知道没有类实现IExample将需要任何构造函数参数,但我不知道如何在代码中指定它,所以它是我 - 而不是编译器 - 知道......)

这可能吗?我该怎么做呢?

更新:我现在尝试了几种建议的方法,但是就所有这些方法而言Activator.CreateInstance(type),我得到了一个System.MissingMethodException,因为我"无法创建接口的实例".这是我的代码:

var tasks = AppDomain.CurrentDomain.GetAssemblies()
    .SelectMany(a => a.GetTypes())
    .Where(t => typeof(IBootstrapperTask).IsAssignableFrom(t))

    // This line is where it fails
    .Select(t => Activator.CreateInstance(t) as IBootstrapperTask)

    .ToArray();
new AutoMapperBootstrapper(tasks).Initialize();
Run Code Online (Sandbox Code Playgroud)

没有这个as条款我没有看到任何异常,但我得到了一个object[],我需要一个IBootstrapperTask[]在摘录的最后一行的构造函数.我已经尝试了各种方法来投射它,但似乎都没有效果.

Jar*_*Par 29

这可以通过Reflection完成.例如

var interfaceType = typeof(IExample);
var all = AppDomain.CurrentDomain.GetAssemblies()
  .SelectMany(x => x.GetTypes())
  .Where(x => interfaceType.IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract)
  .Select(x => Activator.CreateInstance(x));
Run Code Online (Sandbox Code Playgroud)

注意:这只会创建IExample当前加载的程序集的实例AppDomain.这可能与当前进程中加载​​的所有程序集不同.但是对于许多类型的应用程序,这将是等效的.

  • 更重要的是,它只包含已经*加载*的程序集.可能还有其他*已被*引用*但尚未加载.就个人而言,我更喜欢保持一切明确:) (4认同)

Jon*_*eet 8

您需要知道要查看的程序集列表,但LINQ使它相对容易:

var instances = (from assembly in assemblies
                 from type in assembly
                 where !type.IsAbstract && 
                       type.IsClass &&
                       type.IsPublic &&
                       !type.IsGenericType &&
                       typeof(IExample).IsAssignableFrom(type)
                 let ctor = type.GetConstructor(Type.EmptyTypes)
                 where ctor != null && ctor.IsPublic
                 select (IExample) Activator.CreateInstance(type))
                .ToList();
Run Code Online (Sandbox Code Playgroud)

您可能会想到要添加的其他一些限制,但它们很容易表达:)

instances那将是一个List<IExample>.

编辑:我怀疑我的代码将在你的代码没有的地方工作,因为我特意排除了非类.我的猜测是,当你的代码试图实例化界面本身,即ttypeof(IBootstrapperTask).


Chr*_*oph 5

你需要动态发生吗?有没有时候你可能有一个你不想创建的?在我看来,这是依赖注入(可以配置)的一个很好的例子.例如,Unity有一个ResolveAll方法.

从以上链接;

IEnumerable<IMyObject> objects = myContainer.ResolveAll<IMyObject>();
Run Code Online (Sandbox Code Playgroud)