【问题标题】:Factory pattern with Managed Ext Framework (MEF)带有托管 Ext 框架 (MEF) 的工厂模式
【发布时间】:2019-10-03 00:33: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;
    }
}

【问题讨论】:

    标签: c# mef factory-pattern


    【解决方案1】:

    如果您希望在每次调用 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 工厂,然后您将拥有一组提供者。

    附: [ImportMany] 在你的例子中 objectTypes 成员是多余的,因为你没有组成这个类型(我不相信你甚至可以因为它是静态的),你只是从 GetExports 的输出中以编程方式设置它

    【讨论】:

    • 感谢 EdZ 的更新。有用。我还没有意识到我的 objectTypes 在类级别是静态的,并且每次都给出相同的对象。来到您的 Q on Constructor 参数,我更改了 classA 和 ClassB def 并删除了构造函数的参数。现在它可以工作了,每次它都会给我新的实例。
    【解决方案2】:

    我可以解决这个问题

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

    【讨论】:

    • 虽然它现在可以工作,但我看到每次它返回相同的实例。我在 ClassA 和 ClassB 之上添加了 [PartCreationPolicy(System.ComponentModel.Composition.CreationPolicy.NonShared)]。有什么建议吗?
    【解决方案3】:

    您可以尝试以下解决方案

    //项目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");
                }
            }
    

    【讨论】:

      猜你喜欢
      • 2023-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-19
      • 1970-01-01
      相关资源
      最近更新 更多