带有托管扩展框架(MEF)的工厂模式

本文关键字:MEF 工厂 模式 框架 扩展 | 更新日期: 2023-09-27 18:26:10

我正在尝试用MEF实现工厂模式。

这是我的解决方案

核心项目

IClass
ObjectFactory static Class(This is where the problem is)

项目A

[Export(typeof(IClass))]
[ExportMetadata("Type", "TypeA")]
public classA : IClass
{}

项目B

[Export(typeof(IClass))]
[ExportMetadata("Type", "TypeB")]
public classB : IClass
{}

当我试图动态创建对象时,我遇到了问题

这是工厂级:

public static class ObjectFactory
{
    private static readonly CompositionContainer _container;
    [ImportMany]
    public static IEnumerable<Lazy<IClass, IMetaData>> objectTypes;
    static ObjectFactory()
    {
        AggregateCatalog catalog = new AggregateCatalog();
        catalog.Catalogs.Add(new DirectoryCatalog(Environment.CurrentDirectory));
        _container = new CompositionContainer(catalog);
        try
        {
            objectTypes = _container.GetExports<IClass, IMetaData>();
        }
        catch (CompositionException compositionException)
        {
            Console.WriteLine(compositionException.ToString());
            Console.ReadLine();
        }
    }
    public static IClass CreateObject(ObectType objectType)
    {
        IClass outProvider;
        Type typeToLoad = objectTypes.Where(x => x.Metadata.Type == objectType.ToString()).FirstOrDefault().GetType();
        outProvider = (IClass)Activator.CreateInstance(typeToLoad);
        return outProvider;
    }
}

带有托管扩展框架(MEF)的工厂模式

如果您希望在每次调用CreateObject时都提供一个新的"NonShared"实例,那么我建议进行重构。

private static readonly CompositionContainer _container;
static ObjectFactory()
{       
    var directoryCatalog = new DirectoryCatalog(Environment.CurrentDirectory)
    _container = new CompositionContainer(directoryCatalog);        
}
public static IClass CreateObject(ObectType objectType)
{       
    var objectTypes objectTypes = new List<Lazy<IClass, IMetaData>>();
    try
    {
       objectTypes.AddRange(_container.GetExports<IClass, IMetaData>());
    }
    catch (CompositionException compositionException)
    {
        Console.WriteLine(compositionException.ToString());
        Console.ReadLine();
    }
    return objectTypes.FirstOrDefault(x => x.Metadata.Type == objectType.ToString());
}

您可以看到,每次MEF组合类型或调用GetExports(以及该函数的所有其他重载)时,它都会解析新实例(即非共享实例)。或者,你可以出口IClass工厂,然后你会有一个供应商的集合。

在您的示例中,objectTypes成员上的p.S.[ImportMany]是多余的,因为您没有编写此类型(我认为您甚至不能编写,因为它是静态的),您只是从GetExports 的输出中以编程方式设置它

我可以修复问题

public static IClass CreateObject(ObectType objectType)
    {
        return objectTypes.Where(x => x.Metadata.Type == objectType.ToString()).FirstOrDefault().Value;
    }

您可以尝试以下解决方案

//项目A

[PartCreationPolicy(CreationPolicy.NonShared)]
[Export("TypeA", typeof(IClass))]
public classA : IClass
{}

//项目B

 [PartCreationPolicy(CreationPolicy.NonShared)]
    [Export("TypeB", typeof(IClass))]
    public classB : IClass
    {}

//使用泛型创建新对象方法的类

 public static class ObjectFactory
    {
        private static readonly CompositionContainer _container;
        [ImportMany]
        public static IEnumerable<Lazy<IClass, IMetaData>> objectTypes;
        static ObjectFactory()
        {
            AggregateCatalog catalog = new AggregateCatalog();
            catalog.Catalogs.Add(new DirectoryCatalog(Environment.CurrentDirectory));
            _container = new CompositionContainer(catalog);
        }
    //get object method
        public static T CreateObject<T>(string objectType)
        {
            try
                {
                    return _container?.GetExportedValueOrDefault<T>(objectType);
                }
                catch (Exception)
                {
                }
                return null;
        }
    }

//类创建对象

public class classToConsume 
        {
          public void CreateMEFInstances()
           {

              IClass objClassA = ObjectFactory.CreateObject<IClass>("TypeA");
               IClass objClassB = ObjectFactory.CreateObject<IClass>("TypeB");
            }
        }