我可以使用MEF创建可扩展工厂吗? [英] Can I use MEF to create an extensible factory?

查看:54
本文介绍了我可以使用MEF创建可扩展工厂吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先让我说,我是在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆