【问题标题】:MEF Property Always Returning NullMEF 属性始终返回 Null
【发布时间】:2011-08-18 11:43:04
【问题描述】:

原始源代码

我的 BusinessObjects.dll 文件中有一个简单的业务对象:

namespace BusinessObjects
{
    public class MyClass
    {
        public MyClass()
        {
            DateTime = DateTime.Now;
        }

        public DateTime DateTime { get; set; }
    }
}

在我的 SharedUI.dll 中,我有这个“上下文提供者”类,我用它来保存对当前选定的 MyClass 的引用 - 请记住这是一个简单的示例 :)...

namespace SharedUI
{
    public class AppContext
    {
        [Export]
        public MyClass SelectedMyClass { get; private set; }

        public void SetupContext(MyClass myClass)
        {
            SelectedMyClass = myClass;
        }

        public static AppContext Context
        {
            get
            {
                if (context == null)
                {
                    context = new AppContext();
                }
                return context;
            }
        }

        private static AppContext context;
    }
}

我的 MefTest.exe 有这个类:

namespace MefTest
{
    public class Program
    {
        [Import]
        public MyClass MyClass { get; set; }

        private void Compose()
        {
            var ventSystem = new MyClass();
            AppContext.Context.SetupContext(ventSystem);

            var executingAssembly = new AssemblyCatalog(Assembly.GetExecutingAssembly());
            var contextAssembly = new AssemblyCatalog(Assembly.LoadFile(string.Format(@"{0}\SharedUI.dll", Environment.CurrentDirectory)));
            var catalog = new AggregateCatalog(executingAssembly, contextAssembly);

            var container = new CompositionContainer(catalog);

            container.ComposeParts(this);
        }

        private void Run()
        {
            Compose();

            // MyClass is always null in the next line?
            Console.WriteLine(MyClass.DateTime.ToString());

            Console.ReadKey();
        }

        private static void Main(string[] args)
        {
            var p = new Program();
            p.Run();
        }
    }
}

我是 MEF 菜鸟,所以请多多包涵 :)

根据 Daniel Plaisted 的建议更新源代码

MyClass 源是一样的...

SharedUI.dll 现在看起来像这样:

namespace SharedUI
{
    [Export]
    public class AppContext
    {
        [Export(typeof(MyClass))]
        public MyClass SelectedMyClass { get; private set; }

        public void SetupContext(MyClass myClass)
        {
            SelectedMyClass = myClass;
        }
    }
}

MefTest.exe 现在看起来像这样:

namespace MefTest
{
    public class Program
    {
        [Import]
        public MyClass MyClass { get; set; }

        [Import]
        public AppContext AppContext { get; set; }

        private void Compose()
        {
            var executingAssembly = new AssemblyCatalog(Assembly.GetExecutingAssembly());
            var contextAssembly = new AssemblyCatalog(Assembly.LoadFile(string.Format(@"{0}\SharedUI.dll", Environment.CurrentDirectory)));
            var catalog = new AggregateCatalog(executingAssembly, contextAssembly);

            var container = new CompositionContainer(catalog);

            container.ComposeParts(this);

            var myClass = new MyClass();
            AppContext.SetupContext(myClass);
        }

        private void Run()
        {
            Compose();

            // AppContext.SelectedMyClass is NOT null in the next line... which is good I guess :)
            Console.WriteLine(AppContext.SelectedMyClass.DateTime.ToString());

            // MyClass is always null in the next line?
            Console.WriteLine(MyClass.DateTime.ToString());

            Console.ReadKey();
        }

        private static void Main(string[] args)
        {
            var p = new Program();
            p.Run();
        }
    }
}

我做错了什么,因为我无法让它工作?

【问题讨论】:

  • 您是否确认它会将GUI 加载到AssemblyCatalog 中?
  • @Jonas:“GUI”是什么意思?是包含 Program-class、AppContext-class 还是 MyClass-class...的项目?
  • 对不起,我混淆了 2 个不同的 SO 问题 :) 我的意思是 AppContext 类。您是否验证过它是由 MEF 加载的?
  • @Jonas:我想是的。如果我从 AppContext 类中删除 Export-attribute,container.ComposeParts(this) 会引发异常:“未找到与约束匹配的有效导出 '((exportDefinition.ContractName == "BusinessObjects.MyClass")... "

标签: c# import export properties mef


【解决方案1】:

当 MEF 需要获取类属性上的 Export 时,它会创建该类的实例并调用属性 getter。因此,MEF 正在创建您的 AppContext 的新实例,与静态 AppContext.Context 实例不同。 MEF 创建的实例没有设置 SelectedMyClass 属性,这就是您的导入最终为空的原因。

【讨论】:

  • 我已经根据您的建议更新了原始问题 - 但是我无法让它工作?我在这里错过了什么?
  • @kenneth 您修改后的样本有不同的问题。 MEF 只获取一次导出的值,不知道它以后是否会更改。当您调用 ComposeParts(this) 时,它会提取 MyClass 导出的值。当您随后修改该属性时,它对导出的值没有影响。
【解决方案2】:

问题是:

    [Import]        public MyClass MyClass { get; set; }

没有为 MyClass 定义 [Export]。 MEF 将根据它“知道”的东西编写这个应用程序,因为它不知道“MyClass”......

我注意到了这个:

    [Export]        public MyClass SelectedMyClass { get; private set; }

这意味着您试图欺骗 MEF 不时更新它的某个部分?对此的解决方案是创建一个包含“运行时”对象的自定义目录,您可以在其中随时更新 MyClass 的导出值。当前的实现永远不会解析 MyClass...

[编辑:] 你也可以装饰一个成员,但你必须在那里添加类类型。所以这会起作用:

[Export(typeof(MyClass)] public MyClass SelectedMyClass { get; private set; }

【讨论】:

  • 不幸的是,这似乎没有解决它:(
【解决方案3】:

您将Export 属性放在错误的位置。

你应该像这样把它放在MyClass的定义上:

namespace BusinessObjects
{
[Export]
public class MyClass
{
    public MyClass()
    {
        DateTime = DateTime.Now;
    }

    public DateTime DateTime { get; set; }
}
}

然后在需要此类实例的任何地方使用 [Import] 属性。

备注:您不能使用 MEF 移动类的特定实例(不是这样)。 MEF 用于创建请求类型的实例并将它们注入指定的位置。

要了解有关 MEF 的更多信息,请查看项目页面CodePlex

【讨论】:

  • 如果我正在阅读文档link,Export 属性可用于类、方法、属性和字段...尤其是备注部分中的以下引用引起了我的兴趣:“ ExportAttribute 可以修饰整个类,也可以修饰类的属性、字段或方法。如果修饰了整个类,则该类的实例就是导出的对象。如果修饰了类的成员,导出的对象将是修饰成员的值。"
  • 试试 [Export(typeof(MyClass)] public MyClass SelectedMyClass { get; private set; }
  • @maartenba:不幸的是,这似乎没有解决它:(
猜你喜欢
  • 2018-02-11
  • 2020-05-24
  • 2018-02-24
  • 1970-01-01
  • 2016-05-31
  • 2015-08-15
  • 2012-03-18
  • 2016-11-04
  • 2016-07-28
相关资源
最近更新 更多