Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Giving a plugin-class a humanly readable name

I'm creating a plugin system for my application and I would like for the plugins to expose a humanly readable name. The application will show a list of available plugins, in this list the name need to be available.

I want to make it very clear for the developers of the plugins what they need to do to make their plugins work.

Currently I'm making the plugin-classes implement an interface and the interface require a property "ConsumerName" to be implemented. However, this requires the main application to create an instance of each plugin, in order to use the CunsumerName property, just to show the list.

public interface IDataConsumer : IDisposable
{
    string ConsumerName { get; }

    void Consume(DataRowSet rows);

    ...
}

Is there any way to force the plugins classes to supply meta-data without creating instances of each type?

My fallback plan is to use reflection and some Attribute on each class, but I don't think that Attributes can be forced using interfaces.

like image 595
Peter Henell Avatar asked Mar 11 '13 12:03

Peter Henell


2 Answers

No, attributes can't be made part of the contract for an interface. But they can be highly recommended.

What I've done in the past is made an attribute such as:

[AttributeUsage(AttributeTargets.Class)]
public class PluginNameAttribute : Attribute {
    public string ConsumerName { get; set; }
}

If a programmer chooses to decorate his class with that attribute, then great. If not, you can fall back on the class name itself:

var consumerName = type.Name;
var nameAttribute = type.GetCustomAttributes(typeof(PluginNameAttribute), true)
    .FirstOrDefault() as PluginNameAttribute;
if (nameAttribute != null) {
    var attributeName = nameAttribute.ConsumerName;
    if (!string.IsNullOrEmpty(attributeName)) {
        consumerName = attributeName;
    }
}

It shouldn't be too much to ask of plugin developers to use the attribute if it's documented that they should do so.

like image 116
ken Avatar answered Oct 08 '22 09:10

ken


Normally I would say "no there is not". That's because there are two mechanisms that allow information to be pulled out of types without requiring an instance to be created: static members and attributes. Since there is no overlap between these mechanisms and interfaces, you cannot satisfy all of your stated requirements at the same time.

However, what's wrong with the attribute-based solution? Certainly you cannot force the presence of the attribute on pain of a failed compile, but you can do that when loading the plugin (or even earlier).

like image 44
Jon Avatar answered Oct 08 '22 09:10

Jon