我可以使用MEF创建可扩展工厂吗? [英] Can I use MEF to create an extensible factory?
问题描述
首先让我说,我是在MEF经验有限的情况下才来到这里的,并且以前使用Castle和Unity都实现了我的目标.我希望可以使用MEF进行类似的操作.
Let me start by saying that I am coming at this with limited MEF experience and have accomplished my goals using both Castle and Unity previously. I'm hoping something similar can be done with MEF.
简而言之,我需要一个可以通过名称实例化对象的工厂类.更具体地说,我将有一个抽象基类,例如:
In short, what I need is a factory class that can instantiate objects by name. More specifically, I will have an abstract base class such as:
public abstract class TheBaseClass { ... }
从基类派生出许多子类:
There will be any number of subclasses that derive from the base class:
public class OneSubClass : TheBaseClass { ... }
public class AnotherSubClass : TheBaseClass { ... }
在运行时,我需要一个可以调用的工厂,传递一个键"值,以获取返回的特定子类实例,例如:
At runtime, I need a factory that I can call, passing a 'key' value, to get the specific subclass instance returned like:
var key = "AnotherSubClass";
TheBaseClass instance = TheFactory.CreateInstance(key);
在Castle和Unity中,我可以使用'key'作为名称注册该类型,并在尝试从容器中解析实例时将此值用作查找.我以为我可以使用ExportMetadata来完成同样的事情,但是我仍然处于停滞状态.
In Castle and Unity, I could register the type with 'key' as the name and use this value as a lookup when trying to resolve the instance from the container. I thought I might be able to accomplish the same thing using ExportMetadata but am at a stand-still how I can do it.
这种方法(如果有更好的方法)的原理是,我需要在运行时实例化一个强类型子类,而在编译时不知道该类型,因为应用程序是可扩展的,并且(导出的)类型可以通过外部程序集添加.
The rationale behind this approach (in case there's a better way), is that I need to instantiate a strongly-typed subclass at runtime without any knowledge of that type at compile time because the application is extensible and (exported) types can be added through external assemblies.
有什么想法吗?
推荐答案
我建议使用强类型名称以避免输入错误.
I would suggest to use strongly typed names to avoid mistyping errors.
为此,首先需要创建一个将用作键的枚举:
To do so, first you need to create an enum that you will use as a key:
public enum DerivedClassesKeyEnum
{
ONE,
TWO
}
然后您创建一个自定义属性:
Then you create a custom attribute:
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class)]
public class DirivedBaseExportAttribute : ExportAttribute
{
public DirivedBaseExportAttribute()
:base(typeof(TheBaseClass))
{ }
public DerivedClassesKeyEnum DerivedClassId { get; set; }
}
接下来,您将此属性应用于您派生的类:
Next, you apply this attribute to yuor derived classes:
[DirivedBaseExport(DerivedClassId=DerivedClassesKeyEnum.ONE)]
public class OneSubClass : TheBaseClass
{
}
在将导入这些类的部分中,您声明一个接口:
In the part that will import these classes you declare an interface:
public interface IDerivedClassMetadata
{
DerivedClassesKeyEnum DerivedClassId{get;}
}
最后一点,在您的FactoryClass中:
And last bit, in your FactoryClass:
public class TheFactory
{
[ImportMany]
public static IEnumerable<Lazy<TheBaseClass, IDerivedClassMetadata>> DerivedClasses { get; set; }
public static TheBaseClass CreateInstance(DerivedClassesKeyEnum id)
{
return DerivedClasses.Single(c => c.Metadata.DerivedClassId == id).Value;
}
}
这是简化的代码,仅用于说明用法.
It is simplified code just to illustrate the usage.
这篇关于我可以使用MEF创建可扩展工厂吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!