简体   繁体   中英

MEF, can I export/import classes with multiple MetaDataAttribute decorations?

How can I make the following code work? It throws an error saying that there are two meta data attributes of identical names, though I do not see why.

The error message is as follows:

An unhandled exception of type 'System.InvalidOperationException' occurred in System.ComponentModel.Composition.dll

Additional information: Member or Type 'ConsoleApplication2.DoSomeMagic' contains multiple metadata entries with the name 'PluginName'. The metadata entries could be coming from the ExportMetadataAttribute or from a property of a custom metadata attribute. Either remove the duplicate entries or enable the metadata entry with name 'PluginName' to allow multiple entries via the IsMultiple property on ExportMetadataAttribute or AttributeUsage.AllowMultiple on custom metadata attributes.

class Program
{
    static void Main(string[] args)
    {
        var program = new Program();
        program.Test();
    }

    private void Test()
    {
        //Export
        var catalog = new AssemblyCatalog(this.GetType().Assembly);
        var container = new CompositionContainer(catalog);
        container.ComposeParts(this);

        //Import Meta Data
        var import1 = container.GetExports<IMagic1, IPluginAttributeView>().Select(e => new PluginAttribute(e.Metadata));

    }
}

public interface IPluginAttributeView
{
    string PluginName { get; set; }
    string PluginConfigurationName { get; set; }
    string PluginCategory { get; set; }
    Type PluginType { get; set; }
}

[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class PluginAttribute1 : ExportAttribute, IPluginAttributeView
{
    public string PluginName { get; set; }
    public string PluginConfigurationName { get; set; }
    public string PluginCategory { get; set; }
    public Type PluginType { get; set; }

    public PluginAttribute1(string pluginName, string pluginConfigurationName, string pluginCategory, Type pluginType)
        : base(pluginType)
    {
        PluginName = pluginName;
        PluginConfigurationName = pluginConfigurationName;
        PluginCategory = pluginCategory;
        PluginType = pluginType;
    }
}

[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class PluginAttribute2 : ExportAttribute, IPluginAttributeView
{
    public string PluginName { get; set; }
    public string PluginConfigurationName { get; set; }
    public string PluginCategory { get; set; }
    public Type PluginType { get; set; }

    public PluginAttribute2(string pluginName, string pluginConfigurationName, string pluginCategory, Type pluginType) : base(pluginType)
    {
        PluginName = pluginName;
        PluginConfigurationName = pluginConfigurationName;
        PluginCategory = pluginCategory;
        PluginType = pluginType;
    }
}

public class PluginAttribute
{
    public string PluginName { get; set; }
    public string PluginConfigurationName { get; set; }
    public string PluginCategory { get; set; }
    public Type PluginType { get; set; }

    public PluginAttribute(IPluginAttributeView view)
    {
        PluginName = view.PluginName;
        PluginConfigurationName = view.PluginConfigurationName;
        PluginCategory = view.PluginCategory;
        PluginType = view.PluginType;
    }
}


public interface IMagic1
{
    void DoMagic1();
}

public interface IMagic2
{
    void DoMagic2();
}

[PluginAttribute1("PluginName1", "PluginConfig1.json", "Magic1", typeof(IMagic1))]
[PluginAttribute2("PluginName2", "PluginConfig2.json", "Magic2", typeof(IMagic2))]
public class DoSomeMagic : IMagic1, IMagic2
{
    public void DoMagic1()
    {

    }

    public void DoMagic2()
    {

    }
}

I found the solution after digging through many MEF related blogs and articles. The problem seemed that the imported MetaData is of type IDictionary<string, object . I hope it helps some that may have struggled with similar issue:

class Program
{
    static void Main(string[] args)
    {
        var program = new Program();
        program.Test();
    }

    private void Test()
    {
        //Export
        var catalog = new AssemblyCatalog(this.GetType().Assembly);
        var container = new CompositionContainer(catalog);
        container.ComposeParts(this);

        //Import Meta Data
        var imports = container.GetExports<IMagic1, PluginAttributeView>().Select(e => e.Metadata.Attributes).ToList();

        var results = new List<PluginAttribute>();
        foreach (var import in imports)
        {
            foreach (var plugin in import)
            {
                if (plugin.PluginType.Equals(typeof(IMagic1)))
                {
                    results.Add(plugin);
                }
            }
        }
    }
}

public interface IPluginAttributeView
{
    string PluginName { get; set; }
    string PluginConfigurationName { get; set; }
    string PluginCategory { get; set; }
    Type PluginType { get; set; }
}

public class PluginAttributeView
{
    public List<PluginAttribute> Attributes { get; set; }

    public PluginAttributeView(IDictionary<string, object> aDict)
    {
        string[] p1 = aDict["PluginName"] as string[];
        string[] p2 = aDict["PluginConfigurationName"] as string[];
        string[] p3 = aDict["PluginCategory"] as string[];
        Type[] p4 = aDict["PluginType"] as Type[];

        Attributes = new List<PluginAttribute>();
        for (int i = 0; i < p1.Length; i++)
        {
            Attributes.Add(new PluginAttribute(p1[i], p2[i], p3[i], p4[i]));
        }
    }
}

[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class PluginAttribute : ExportAttribute, IPluginAttributeView
{
    public string PluginName { get; set; }
    public string PluginConfigurationName { get; set; }
    public string PluginCategory { get; set; }
    public Type PluginType { get; set; }

    public PluginAttribute(string pluginName, string pluginConfigurationName, string pluginCategory, Type pluginType) : base(pluginType)
    {
        PluginName = pluginName;
        PluginConfigurationName = pluginConfigurationName;
        PluginCategory = pluginCategory;
        PluginType = pluginType;
    }
}

public interface IMagic1
{
    void DoMagic1();
}

public interface IMagic2
{
    void DoMagic2();
}

[PluginAttribute("PluginName1", "PluginConfig1.json", "Magic1", typeof(IMagic1))]
[PluginAttribute("PluginName2", "PluginConfig2.json", "Magic2", typeof(IMagic2))]
public class DoSomeMagic : IMagic1, IMagic2
{
    public void DoMagic1()
    {

    }

    public void DoMagic2()
    {

    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM