实例化实现特定接口的所有类
我有一个接口 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();
如果没有 as
子句,我看不到任何异常,但我得到了一个 object[]
,并且我需要一个 IBootstrapperTask[ ]
为摘录最后一行的构造函数。我尝试了各种方法来投射它,但似乎都不起作用。
I have an interface IExample
, and a set of classes ClassOne
, ClassTwo
and ClassThree
, all defined in different namespaces. I will possibly remove either of the classes, or add a new one in a new place, at a later stage in development.
Now, I want to find all types that implement IExample
at runtime, and instantiate them. (I know on beforehand that no class implementing IExample
will ever need any constructor arguments, but I don't know how to specify that in code, so it's me - not the compiler - that knows...)
Is this possible? How do I go about to do it?
Update: I've now tried several of the approaches suggested, but on all of them, the line Activator.CreateInstance(type)
, I get a System.MissingMethodException because I "cannot create an instance of an interface." This is my code:
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();
Without the as
clause I don't see any exception, but I'm given an object[]
, and I need an IBootstrapperTask[]
for the constructor on the last line in the excerpt. I've tried various ways to cast it, but none seem to work.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这可以通过反射来完成。例如,
注意:这只会从当前
AppDomain
中加载的程序集创建IExample
的实例。这可能与当前进程中加载的所有程序集不同。然而,对于许多类型的应用程序来说,这将是等效的。This can be done with Reflection. For example
Note: This will only create instances of
IExample
from assemblies loaded in the currentAppDomain
. This can be different than all assemblies loaded in the current process. However for many types of applications this will be equivalent.您需要知道要查看的程序集列表,但是 LINQ 使其相对容易:
您可能会想到添加一些其他限制,但它们很容易表达:)
实例
那么将是一个List
。编辑:我怀疑我的代码可以在你的代码不能工作的地方工作,因为我专门排除了非类。我的猜测是,您的代码正在尝试实例化接口本身,即当
t
为typeof(IBootstrapperTask)
时。You'd need to know a list of assemblies to look in, but then LINQ makes it relatively easy:
You may think of some other restrictions to add, but they're pretty easy to express :)
instances
will then be aList<IExample>
.EDIT: I suspect my code will work where yours didn't, because I'm specifically excluding non-classes. My guess is that your code is trying to instantiate the interface itself, i.e. when
t
istypeof(IBootstrapperTask)
.您需要动态发生这种情况吗?是否有时您可能不想创建一个?在我看来,这是依赖注入的一个很好的例子(可以配置)。例如,Unity 有一个 ResolveAll方法 。
来自上面的链接;
Do you need this to happen dynamically? Are there ever times when you might have one that you don't want to create? Seems to me that this is a good case for dependency injection (which can be configured). For example Unity has a ResolveAll method .
From the above link;
尝试使用反射来获取实现
IExample
的类型。此示例查看当前程序集,但您可以轻松传递不同的程序集:Try using reflection to get the types implementing
IExample
. This example looks at the current assembly but you could easily pass a different assembly: