C # / MEF не работает с базовым классом без конструктора без параметров - PullRequest
5 голосов
/ 26 января 2012

У меня есть класс Prim, который реализует интерфейс IPrimitiveDecomposer для MEF и наследует базовый класс Node.

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;}
}

Однако, когда я наследую класс, не имеющий конструктора без параметров, Mpose ComposeParts ()Метод не может импортировать объект Prim.Я добавил атрибут ImportingConstructor после этой страницы в MSDN , так как получил ошибку компиляции без атрибута.

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

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

Код, который не работает, выглядит следующим образом.Когда вы предоставляете конструктор без параметров для класса Node, он работает.

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 Ответ

9 голосов
/ 26 января 2012

Атрибут ImportingConstructor работает только тогда, когда параметры конструктора являются объектами, экспортируемыми в MEF.Конструкторы Prim(int val) терпят неудачу при компоновке, потому что MEF не знает, какое значение предоставить конструктору.

Этот конкретный сценарий выглядит более подходящим для заводского шаблона MEF.

interface IPrimitiveDecomposerFactory {
  IPrimitiveDecomposer Create(int value);
}

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

Теперь код может импортировать IPrimitiveDecomposerFactory и использовать его для создания IPrimitiveDecomposer экземпляра на основе определенных int значений

...