【问题标题】:Initializing ExportFactory using MEF使用 MEF 初始化 ExportFactory
【发布时间】:2014-06-10 03:19:33
【问题描述】:
  1. 场景
    1. 应用程序有多个部分。
    2. 每个部分都在单独的dll中并实现接口IFoo
    3. 所有此类 dll 都存在于同一目录中(插件)
    4. 应用程序可以实例化每个部分的多个实例

下面是接口、part(export) 和 import 的代码 sn-p。我遇到的问题是,“工厂”对象是用空列表初始化的。

但是,如果我尝试 container.Resolve(typeof(IEnumerable)) ,我确实会得到部件的对象。但这不符合我的目的(第 4 点)。谁能指出我在这里做错了什么?

public interface IFoo
{
    string Name { get; }
}

public interface IFooMeta
{
    string CompType { get; }
}

在单独的 Dll 中实现 IFoo

[ExportMetadata("CompType", "Foo1")]
[Export(typeof(IFoo)), PartCreationPolicy(CreationPolicy.NonShared)]
public class Foo1 : IFoo
{
    public string Name
    {
        get { return this.GetType().ToString(); }
    }
}

加载所有部分并根据需要实例化它们的主应用程序

class PartsManager
    {
        [ImportMany]
        private IEnumerable<ExportFactory<IFoo, IFooMeta>> factories;

        public PartsManager()
        {
            IContainer container = ConstructContainer();    
            factories = (IEnumerable<ExportFactory<IFoo, IFooMeta>>)
                   container.Resolve(typeof(IEnumerable<ExportFactory<IFoo, IFooMeta>>));    
        }    

        private static IContainer ConstructContainer()
        {
            var catalog = new DirectoryCatalog(@"C:\plugins\");
            var builder = new ContainerBuilder();         
            builder.RegisterComposablePartCatalog(catalog);

            return builder.Build();
        }

        public IFoo GetPart(string compType)
        {
            var matchingFactory = factories.FirstOrDefault(
                x => x.Metadata.CompType == compType);
            if (factories == null)
            {
                return null; 
            }
            else
            {
                IFoo foo = matchingFactory.CreateExport().Value;
                return foo;
            }
        }
    }

【问题讨论】:

  • .net 框架 BCL 中没有 ContainerBuilder。你在使用 autofac 吗?
  • 是的,我正在使用 autofac,
  • Mhm...我猜问题出在autofac方面...解决方法属于autofac,而不是mef。希望熟悉autofac的人能插嘴。祝你好运。

标签: c# mef autofac


【解决方案1】:

这似乎是 ContainerBuilder 的问题。我尝试了使用 CompositionContainer 的替代方法,并且没有障碍。粘贴修改方法的代码 sn-p。

    public PartsManager()
    {
         ConstructContainer();
    }

    private void ConstructContainer()
    {
        var catalog = new DirectoryCatalog(@"C:\plugins\");
        var container = new CompositionContainer(catalog);
        container.ComposeParts(this);
        container.SatisfyImportsOnce(this);
    }

【讨论】:

    【解决方案2】:

    它似乎是 Autofac 中的 known issue,目前以“无法修复”的分辨率关闭。

    如果您像下面这样从 Autofac 中删除依赖项,它将起作用:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel.Composition.Hosting;
    using System.Linq;
    using System.ComponentModel.Composition;
    using System.Reflection;
    
    namespace SO24132313
    {
        public interface IFoo
        {
            string Name { get; }
        }
    
        public interface IFooMeta
        {
            string CompType { get; }
        }
    
        [ExportMetadata("CompType", "Foo1")]
        [Export(typeof(IFoo)), PartCreationPolicy(CreationPolicy.NonShared)]
        public class Foo1 : IFoo
        {
            public string Name
            {
                get { return GetType().ToString(); }
            }
        }
    
    
        class PartsManager
        {
            [ImportMany]
            private IEnumerable<ExportFactory<IFoo, IFooMeta>> factories;
    
            public PartsManager()
            {
                ConstructContainer(this);
            }
    
            private static void ConstructContainer(PartsManager p)
            {
                var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
                var c = new CompositionContainer(catalog);
                c.ComposeParts(p);
            }
    
            public IFoo GetPart(string compType)
            {
                var matchingFactory = factories.FirstOrDefault(
                    x => x.Metadata.CompType == compType);
                if (factories == null)
                {
                    return null;
                }
                else
                {
                    IFoo foo = matchingFactory.CreateExport().Value;
                    return foo;
                }
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                PartsManager a = new PartsManager();
                IFoo bla = a.GetPart("Foo1");
                Console.WriteLine(bla);
            }
        }
    }
    

    【讨论】:

    • 感谢佳沛。我尝试了可行并共享它的替代解决方案。似乎你做了类似的方法。 \
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-07
    • 1970-01-01
    相关资源
    最近更新 更多