IntroRécupérer une liste d'objet qui implémente une interface donnée
Je construis une architecture de plug-in dans mon application. Les plug-ins de mettre en œuvre une interface donnée IBasePlugin, ou une autre interface qui a hérité de l'interface de base:
interface IBasePlugin
interface IMainFormEvents : IBasePlugin
L'hôte est de chargement des assemblages de plug-ins, et crée ensuite l'objet approprié d'une classe d'application de l'IBasePlugin Interface ..
Ceci est la charge de la classe des plug-ins et instancier les objets:
public class PluginCore
{
#region implement singletone instance of class
private static PluginCore instance;
public static PluginCore PluginCoreSingleton
{
get
{
if (instance == null)
{
instance = new PluginCore();
}
return instance;
}
}
#endregion
private List<Assembly> _PlugInAssemblies = null;
/// <summary>
/// Gets the plug in assemblies.
/// </summary>
/// <value>The plug in assemblies.</value>
public List<Assembly> PlugInAssemblies
{
get
{
if (_PlugInAssemblies != null) return _PlugInAssemblies;
// Load Plug-In Assemblies
DirectoryInfo dInfo = new DirectoryInfo(
Path.Combine(
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
"Plugins"
)
);
FileInfo[] files = dInfo.GetFiles("*.dll");
_PlugInAssemblies = new List<Assembly>();
if (null != files)
{
foreach (FileInfo file in files)
{
_PlugInAssemblies.Add(Assembly.LoadFile(file.FullName));
}
}
return _PlugInAssemblies;
}
}
List<IBasePlugin> _pluginsList = null;
/// <summary>
/// Gets the plug ins instances.
/// all the plugins are being instanciated ONCE when this if called for the first time
/// every other call will return the existing classes.
/// </summary>
/// <value>The plug ins instances.</value>
public List<IBasePlugin> PlugInInstances
{
get
{
if (_pluginsList != null) return _pluginsList;
List<Type> availableTypes = new List<Type>();
foreach (Assembly currentAssembly in this.PlugInAssemblies)
availableTypes.AddRange(currentAssembly.GetTypes());
// get a list of objects that implement the IBasePlugin
List<Type> pluginsList = availableTypes.FindAll(delegate(Type t)
{
List<Type> interfaceTypes = new List<Type>(t.GetInterfaces());
return interfaceTypes.Contains(typeof(IBasePlugin));
});
// convert the list of Objects to an instantiated list of IBasePlugin
_pluginsList = pluginsList.ConvertAll<IBasePlugin>(delegate(Type t) { return Activator.CreateInstance(t) as IBasePlugin; });
return _pluginsList;
}
}
La question
Actuellement, un module qui prend en charge les plug-ins, utilise les PlugInInstances propriété pour récupérer les IBasePlugins liste. Ensuite, il itère les objets qui demandent qui implémente une interface enfant donnée.
foreach (IBasePlugin plugin in PluginCore.PluginCoreSingleton.PlugInInstances)
{
if (plugin is IMainFormEvents)
{
// Do something
}
}
Je voudrais améliorer cette technique en ayant une fonction qui reçoit une interface enfant donné, et retourner une liste de ces interfaces. Le hic, c'est qu'aucun casting ne devrait être fait dans l'appelant.
code pseudo:
void GetListByInterface(Type InterfaceType, out List<InterfaceType> Plugins)
Avez-vous une recommandation sur la façon de mettre en œuvre ce?
Avez-vous envisagé d'utiliser Microsoft Managed Extensibility Framework à la place? http://www.codeplex.com/MEF – TrueWill
@TrueWill: Je vais y regarder – Amirshk
@TrueWill: J'ai un code qui fait exactement cela à la maison. Je vais jeter un oeil dans quelques heures. –