Importing other attributes to metadata using C# MEF
Asked Answered
S

1

6

Using some tutorials on the web, I created a metadata class for my needs using the MEF in C#

[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class)]
public class ActionMetadataAttribute : Attribute
{
    public bool HasSettingsDialog { get; set; }
    public bool UseThreadedProcessing { get; set; }
}

public interface IActionMetadata
{
    [DefaultValue(false)]
    bool HasSettingsDialog { get; }

    [DefaultValue(false)]
    bool UseThreadedProcessing { get; }
}

I've got different kind of plugin types, so there is e. g. IHandlerMetadata and HandlerMetadataAttribute. Now I load it via the Lazy helper to allow strictly typed metadata.

[ImportMany(typeof(IActionPlugin))]
private IEnumerable<Lazy<IActionPlugin, IActionMetadata>> _plugins = null;

public ActionManager()
{
    var catalog = new DirectoryCatalog(".");
    var container = new CompositionContainer(catalog);
    container.ComposeParts(this);

    foreach (var contract in _plugins)
    {
        Debug.WriteLine(contract.Metadata.HasSettingsDialog);
    }
}

Works perfectly. Now, I also like to have some information about the plugins. So I've created an PluginInformationAttribute.

[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class)]
public class PluginInformationAttribute : Attribute
{
    public string Name { get; set; }
    public string Title { get; set; }
    public string Author { get; set; }
    public string Url { get; set; }
    public string Contact { get; set; }
    public string Description { get; set; }
    public Version Version { get; set; }
}

The question is now: how can I access this attribute for example in the for loop in the above code snippet? Is there any way or is my design wrong? I don't want to include the PluginInformation stuff to IActionMetadata because I'd like to use it on different types of plugins, e. g. on the IHandlerMetadata.

Sklar answered 10/8, 2014 at 14:8 Comment(2)
If you really need this information as metadata (i.e. you want to filter by its properties before creating the instance), you'll have to change the Interface (metadata view) to include the properties you need to access as metadata.Yippee
Did that now. Works properly altough I don't like it really well. Anyway, there seems to be no other solution. Thanks!Sklar
N
1

If you specify the type of your exporting class as a property of ActionMetadataAttribute, then you can access every attribute of the class by reflection with GetCustomAttributes method

[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class)]
public class ActionMetadataAttribute : Attribute
{
    public bool HasSettingsDialog { get; set; }
    public bool UseThreadedProcessing { get; set; }
    public Type ClassType { get; set; }
}

var attributes = contract.Metadata.ClassType.GetCustomAttributes(typeof(PluginInformationAttribute), true)
Nashner answered 7/11, 2014 at 13:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.