我有一个接口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
.这可能与当前进程中加载的所有程序集不同.但是对于许多类型的应用程序,这将是等效的.
您需要知道要查看的程序集列表,但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>
.
编辑:我怀疑我的代码将在你的代码没有的地方工作,因为我特意排除了非类.我的猜测是,当你的代码试图实例化界面本身,即t
是typeof(IBootstrapperTask)
.
你需要动态发生吗?有没有时候你可能有一个你不想创建的?在我看来,这是依赖注入(可以配置)的一个很好的例子.例如,Unity有一个ResolveAll方法.
从以上链接;
IEnumerable<IMyObject> objects = myContainer.ResolveAll<IMyObject>();
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
9447 次 |
最近记录: |