Reputation: 5024
I'm building an extensible application which will load additional assemblies at runtime through Assembly.LoadFile()
. Those additional assemblies will contain things like WPF resource dictionaries (skins, etc.), plain resources (Resx), and/or plugin classes. The assembly can also contain no public classes, only resources or resource dictionaries.
I'm looking for a way to identify an assembly, things like a friendly name (like "Additional skins" or "Integrated browser"), the functional type of an assembly (SkinsLibrary, SkinsLibrary|PluginLibrary, etc) and additional info (like ConflictsWith(new [] {"SkinsLibrary", "BrowserPlugin").
So far I'm using a convention in naming assemblies (*.Skins.*.dll
, etc.). In each assembly I have an empty, dummy class which is just a placeholder for custom class attributes which hold the actual (assembly-wide) information, but that feels like a hack. Is there some streamlined, standard way to handle this?
I'm developing the central loader system and other developers in my team will develop those additional assemblies, so I'd like to minimize the conventions and plumbing details.
Upvotes: 5
Views: 4110
Reputation: 732
You can use the built-in AssemblyMetadataAttribute
class; it is available since .NET 4.5.
Upvotes: 1
Reputation: 13874
EDIT: I've updated the answer with some more detailed information.
Here is an example how you might accomplish what you want to do.
Start by defining a enum for your different types of plugin types.
public enum AssemblyPluginType
{
Skins,
Browser
}
Add two attributes that will be used to describe the plugins (assembly plugin type and potential conflicts).
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
public sealed class AssemblyPluginAttribute : Attribute
{
private readonly AssemblyPluginType _type;
public AssemblyPluginType PluginType
{
get { return _type; }
}
public AssemblyPluginAttribute(AssemblyPluginType type)
{
_type = type;
}
}
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
public sealed class AssemblyPluginConflictAttribute : Attribute
{
private readonly AssemblyPluginType[] _conflicts;
public AssemblyPluginType[] Conflicts
{
get { return _conflicts; }
}
public AssemblyPluginConflictAttribute(params AssemblyPluginType[] conflicts)
{
_conflicts = conflicts;
}
}
Now you can add these attributes to your assembly.
The following two lines can be added anywhere in the assembly as long as they're outside a namespace. I usually put assembly attributes in the AssemblyInfo.cs
file that can be found in the Properties
folder.
[assembly: AssemblyPluginAttribute(AssemblyPluginType.Browser)]
[assembly: AssemblyPluginConflictAttribute(AssemblyPluginType.Skins, AssemblyPluginType.Browser)]
Now you can use the following code to examine an assembly for specific attributes:
using System;
using System.Reflection;
namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
// Get the assembly we're going to check for attributes.
// You will want to load the assemblies you want to check at runtime.
Assembly assembly = typeof(Program).Assembly;
// Get all assembly plugin attributes that the assembly contains.
object[] attributes = assembly.GetCustomAttributes(typeof(AssemblyPluginAttribute), false);
if (attributes.Length == 1)
{
// Cast the attribute and get the assembly plugin type from it.
var attribute = attributes[0] as AssemblyPluginAttribute;
AssemblyPluginType pluginType = attribute.PluginType;
}
}
}
}
Upvotes: 3
Reputation: 9051
For plugins, I have great experience with MvcTurbine (it can be used with other projects, not only mvc). If you use it in combination with Ninject and define interface for plugin, ie:
IPlugin{
string Name {get;}
someResultType PerformAction(someArgType arg);
}
and, in your plugin dll you register implementation of IPlugin by implementing IServiceRegistrator interface from MvcTurbine, then if you place dll with plugin in bin directory, your plugin implementation will be added to list that is passed into constructor of some class that uses DI and receives List, or you can resolve it from IOC container by hand. It is a lot cleaner than loading your assemblies by hand and inspecting them for interfaces/implementations etc...
If you are interested in this, please ask if anything is unclear and I will elaborate.
Upvotes: 0
Reputation: 176956
I am partially getting information but
you can add Custom AssemblyInfo Attributes which you can see by visiting link..
Upvotes: 2