MEF导入为空。

3
我有一个导入对象无法正常工作,它是空的。最初它是一个 ImportMany,但我将其简化为 Import 以尝试确定问题所在,但是我并没有成功。
我已经查阅了这个网站和谷歌,并遵循了主要思路:
- 不要自己实例化类,让 MEF 来处理它,否则调用 container.getExport() - 仍然无法工作 - 在包含 [Import] 属性的类上放置 [Export],否则容器组合过程不会将其识别为部件(在调试时确认)。
我的代码设置如下(为了简洁起见而简化): Assembly1
public class MyBootstrapper
{
    //Automatically called by ExcelDna library, I do not instantiate this class
    public void AutoOpen()
    {
        var ac1 = new AssemblyCatalog(typeof(XLHandler).Assembly);
        var ac2 = new AssemblyCatalog(typeof(MyComponent).Assembly);

        var agc = new AggregateCatalog();
        agc.Catalogs.Add(ac1);
        agc.Catalogs.Add(ac2);

        var cc = new CompositionContainer(agc);

        try
        {
            cc.ComposeParts(this);
        }
        catch (CompositionException exception) {}
    }
}

[Export]
public class XLHandler
{
    [Import(typeof(IMyComponent))]
    public IMyComponent _component;

    public void SomeMethod()
    {
        //try to use _component but it is null
    }
}

汇编语言2

public interface IMyComponent
{
    //stuff...
}

Assembly3

[Export(typeof(IMyComponent)]
public MyComponent : IMyComponent
{
    //more stuff...
}

有人知道或者有想法为什么MEF容器没有注入XLHandler中的_component变量吗?

我需要在Assembly2中导出/创建一个AssemblyCatalog接口吗?


不是很确定,但是导入属性应该是[Import(typeof(IMycomponent))],对吗? - p.s.w.g
是的,你正在导出为 IMyComponent,所以你也必须按此导入。你可以从导入中删除 typeof 定义,因为你的变量类型已经是 IMyComponent。 - ChrisO
是的,在问题中有个打字错误。我会修复它。 - clicky
2个回答

8

在导入部件时,您可以在属性上使用[Import]属性,或者将其作为构造函数的一部分请求并使用[ImportingConstructor]属性。

使用[Import]属性导入的任何部件都不会在类的构造函数中可用

因此,在您的情况下,请像这样更改XLHandler类:

[Export]
public class XLHandler
{
    [ImportingConstructor]
    public void SomeMethod(MyComponent component)
    {
        _component = component;
       // You can use _component, since it has already been resolved...
    }
}

那么 [Import] 的意义是什么呢?抱歉,我无法理解它。我如何直接注入到属性/类变量中? - clicky
1
在构造函数中,如果您不需要立即解析某个部分,则可以使用 [Import]。它将在构造函数完成后和调用该实例的任何属性/方法之间的某个时间解析。 - Blachshma
好的,我已经将类变量更改为属性(添加了{get;set;}),但它仍然为空。理想情况下,我不想将变量作为方法参数传递,所以我仍然困惑为什么[Import]没有注入该属性。 - clicky
1
如果您试图在构造函数中引用它,它仍将为 null... 如果您想在构造函数中使用它(或从构造函数内部调用的任何方法中),则需要将其作为参数传递给构造函数并使用 [ImportingConstructor] - Blachshma
啊,好的。我没有在构造函数中引用它 - 我没有定义构造函数。我猜因为ExcelDNA库正在实例化这个类,可能是在MEF运行[Import]之前这样做的? - clicky
显示剩余2条评论

2
MyBootstrapper.AutoOpen 中,您需要替换以下内容:
cc.ComposeParts(this);

使用类似以下的东西:

var handler = new XLHandler();
cc.ComposeParts(handler);

或者:

var handler = cc.GetExportedValue<XLHandler>();

由于MyBootstrapper没有导入,因此您无法组合其部件。 ComposeParts不会执行任何操作。

另一种方法是向MyBootstrapper添加导入。例如:

public class MyBootstrapper
{
    [Import]
    XLHandler XLHandler;

    //Automatically called by ExcelDna library, I do not instantiate this class
    public void AutoOpen()
    {
        //Leave your implementation unchanged.
    }
}

顺便说一下,MyComponent 无法编译。

谢谢。我实际上使用了两个答案的组合,但不确定如何接受两者。已经提升了两个答案。 - clicky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接