C#/MEF doesn't work with a base class without parameterless constructor

纵饮孤独 提交于 2019-12-23 11:53:20

问题


I have a Prim class that implements an IPrimitiveDecomposer interface for MEF and inherits Node base class.

public class Node
{
    public Node()
    {
    }
}

public interface IPrimitiveDecomposer
{
    bool Match(Node node);
}

[Export(typeof(IPrimitiveDecomposer))]
public class Prim : Node, IPrimitiveDecomposer
{       
    public bool Match(Node node) {return true;}
}

However, when I inherit a class that doesn't have a parameterless constructor, MEF's ComposeParts() method cannot import the Prim object. I added the attribute of ImportingConstructor following this page in MSDN, as I got compilation error without the attribute.

[Export(typeof(IPrimitiveDecomposer))]
public class Prim : Node, IPrimitiveDecomposer
{
    [ImportingConstructor] 
    public Prim(int val) : base (val)
    {}

    public bool Match(Node node) {return true;}
}

The code that doesn't work is as follows. When you provide the parameterless constructor for the Node class, it works.

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Reflection;

public class Node
{
    public Node(int val)
    {
    }
}

public interface IPrimitiveDecomposer
{
    bool Match(Node node);
}

[Export(typeof(IPrimitiveDecomposer))]
public class Prim : Node, IPrimitiveDecomposer
{
    [ImportingConstructor] 
    public Prim(int val) : base (val)
    {}

    public bool Match(Node node) {return true;}
}

public class Test
{
    [ImportMany(typeof(IPrimitiveDecomposer), AllowRecomposition = true)]
    private IEnumerable<IPrimitiveDecomposer> PrimitiveDecomposers { get; set; }

    void mef()
    {
        // MEF
        var catalog = new AggregateCatalog();
        catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));

        var container = new CompositionContainer(catalog);
        container.ComposeParts(this);
    }

    static void Main()
    {
        var mef = new Test();
        mef.mef();
        var res = mef.PrimitiveDecomposers;

        foreach(var it in res)
        {
            Console.WriteLine(it);
        }
    }
}

回答1:


The ImportingConstructor attribute only works when the parameters to the constructor are MEF exported objects. The Prim(int val) constructors fails composition because MEF doesn't know what value to provide for the constructor.

This particular scenario looks like it's much more suited for a MEF factory pattern.

interface IPrimitiveDecomposerFactory {
  IPrimitiveDecomposer Create(int value);
}

[Export(typeof(IPrimitiveDecomposerFactory))]
sealed class PrimitiveDecomposerFactor : IPrimitiveDecomposerFactory {
  public IPrimitiveDecomposer Create(int value) {
    return new Prim(value);
  }
}

Now code can import the IPrimitiveDecomposerFactory and use it to create IPrimitiveDecomposer instance based on specific int values



来源:https://stackoverflow.com/questions/9023098/c-mef-doesnt-work-with-a-base-class-without-parameterless-constructor

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!