2011-06-15 10 views
5

Estoy construyendo una aplicación extensible que cargará ensamblados adicionales en tiempo de ejecución a través del Assembly.LoadFile(). Esos ensamblajes adicionales contendrán cosas como diccionarios de recursos WPF (máscaras, etc.), recursos simples (Resx) y/o clases de complementos. El ensamblaje tampoco puede contener clases públicas, solo recursos o diccionarios de recursos..Net 4 - Incluye información personalizada en el ensamblado

Estoy buscando una manera de identificar un ensamblaje, cosas como un nombre descriptivo (como "Máscaras adicionales" o "Navegador integrado"), el tipo funcional de un conjunto (SkinsLibrary, SkinsLibrary | PluginLibrary, etc.) y información adicional (como ConflictsWith (new [] {"SkinsLibrary", "BrowserPlugin").

Hasta ahora estoy usando una convención para nombrar ensamblajes (*.Skins.*.dll, etc.). En cada ensamblaje tengo un maniquí vacío clase que es solo un marcador de posición para atributos de clases personalizadas que contienen la información real (en todo el conjunto), pero que se siente como un truco. ¿Hay alguna manera simplificada y estándar para manejar esto?

Estoy desarrollando el sistema de cargador central y otros desarrolladores de mi equipo desarrollarán esos conjuntos adicionales, por lo que me gustaría minimizar las convenciones y los detalles de plomería.

+0

Los archivos de recursos, si tienen el nombre adecuado (name.lang.resx), deben cargarse automáticamente para el idioma actual, si tiene un recurso "predeterminado" definido. Framework hace eso por ti. ¿Por qué necesita cargar recursos manualmente? –

+0

Porque esos archivos de recursos se compilan en un ensamblado y hay muchos de ellos. Por ejemplo, tengo los conjuntos Skin1 y Skin2, y la configuración indica que la aplicación usa Skin1, por lo que la aplicación no debería cargarlos automáticamente. Sin embargo, la aplicación debe conocer la existencia de Skin2 para que el usuario pueda seleccionarla. –

+0

¿Es posible tener máscaras en forma de implementación de alguna interfaz (ISkin?), Entonces ¿usted escribe su propia implementación en una dll y agrega los recursos necesarios a esa dll? Para cada piel, tendría un ensamblaje y todos los recursos necesarios para ese ensamblaje a los que se hace referencia se cargan automáticamente. Solo tendría que preocuparse de que dos máscaras no usen recursos con el mismo nombre (fácil de prevenir al agregar skinname a la convención de nombres). –

Respuesta

3

EDITAR: He actualizado la respuesta con información más detallada.

Aquí hay un ejemplo de cómo puede lograr lo que quiere hacer.
Comience definiendo una enumeración para sus diferentes tipos de tipos de complementos.

public enum AssemblyPluginType 
{ 
    Skins, 
    Browser 
} 

añadir dos atributos que se utilizan para describir los plugins (montaje de tipo plugin y los conflictos potenciales).

[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; 
    } 
} 

Ahora puede agregar estos atributos a su conjunto.

Las siguientes dos líneas se pueden agregar en cualquier parte del ensamblaje, siempre que se encuentren fuera de un espacio de nombres. Normalmente pongo atributos de ensamblaje en el archivo AssemblyInfo.cs que se puede encontrar en la carpeta Properties.

[assembly: AssemblyPluginAttribute(AssemblyPluginType.Browser)] 
[assembly: AssemblyPluginConflictAttribute(AssemblyPluginType.Skins, AssemblyPluginType.Browser)] 

Ahora puede utilizar el siguiente código para examinar un conjunto de atributos específicos:

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; 
      } 
     } 
    } 
} 
+0

Gracias, ¿podrían especificar dónde debo poner esos atributos '[assembly: ...]' y cómo puedo consultar un ensamblaje para esos atributos? –

+0

@Boris: He actualizado la respuesta con más información sobre dónde declarar los atributos de ensamblaje y cómo consultar la información de un ensamblaje. – Patrik

2

estoy parcialmente recibiendo información sino

puede agregar Custom AssemblyInfo Attributes que se puede ver visitando enlace ..

+1

Gracias, esto podría ser justo lo que estoy buscando, lo intentaré. –

0

para los plugins, tengo una gran experiencia con MvcTurbine (puede ser utilizado con otros proyectos, no solo mvc). Si lo usa en combinación con Ninject y definir la interfaz de plug-in, es decir:

IPlugin{ 
    string Name {get;} 
    someResultType PerformAction(someArgType arg); 

} 

y, en su plugin DLL se registra implementación de IPlugin mediante la implementación de la interfaz IServiceRegistrator de MvcTurbine, a continuación, si se coloca DLL con el plugin de bin directorio, su implementación de complemento se agregará a la lista que se pasa al constructor de alguna clase que usa DI y recibe Lista, o puede resolverlo desde el contenedor IOC a mano. Es mucho más limpio que cargar sus ensambles a mano e inspeccionarlos para interfaces/implementaciones, etc. ...

Si está interesado en esto, pregunte si algo no está claro y lo elaboraré.

Cuestiones relacionadas