c# dependency-injection mef constructor-injection

c# - MEF Constructor Injection



dependency-injection constructor-injection (3)

Aunque es tarde para el juego, aquí hay otro enfoque que aprovecha una característica menos conocida de MEF: Exportaciones de propiedades

public class ObjectMother { [Export] public static EditProfile DefaultEditProfile { get { var method = ConfigurationManager.AppSettings["method"]; var version = ConfigurationManager.AppSettings["version"]; return new EditProfile(method,version); } } }

No se requieren usos para ObjectMother para que esto funcione, y no se requieren atributos en EditProfile.

Estoy tratando de descubrir el atributo de Inyección de Constructor de MEF. No tengo idea de cómo le digo que cargue los parámetros del constructor.

Esta es la propiedad que intento cargar

[ImportMany(typeof(BUsers))] public IEnumerable<BUsers> LoadBUsers { get; set; }

Aquí está el código que estoy usando para importar los ensambles.

try { var catalog = new AggregateCatalog(); catalog.Catalogs.Add(new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly())); catalog.Catalogs.Add(new DirectoryCatalog("DI")); var container = new CompositionContainer(catalog); container.ComposeParts(this); }

Aquí está la clase que estoy tratando de cargar

[Serializable] [Export(typeof(BUsers))] public class EditProfile : BUsers { [ImportingConstructor] public EditProfile(string Method, string Version) { Version = "2"; Action = "Edit"; TypeName = "EditProfile"; }


Cuando utiliza el atributo ImportingConstructor, los parámetros para el constructor se convierten en importaciones. Por defecto, lo que está importando (el nombre del contrato) se basa en el tipo de parámetro o propiedad en el que está importando. Entonces, en este caso, el tipo de contrato para ambas importaciones es cadena, y no hay diferencia real entre el primero y el segundo parámetro.

Parece que está intentando usar importaciones para suministrar valores de configuración, que no es necesariamente para lo que fue diseñado. Para que haga lo que desea, debe anular el nombre del contrato para cada uno de los parámetros, como este:

[ImportingConstructor] public EditProfile([Import("Method")] string Method, [Import("Version")] string Version) { }

Entonces necesita exportar para Método y Versión en su contenedor. Una forma de hacerlo es simplemente agregarlos directamente:

var container = new CompositionContainer(catalog); container.ComposeExportedValue("Method", "MethodValue"); container.ComposeExportedValue("Version", "2.0"); container.ComposeParts(this);

(Tenga en cuenta que ComposeExportedValue es en realidad un método de extensión definido en la clase estática AttributedModelServices).

Si desea leer estos valores desde un archivo de configuración de algún tipo, puede crear su propio proveedor de exportación que lea la configuración y proporcione los valores en ella como exportaciones al contenedor.

Una forma alternativa de manejar esto sería importar una interfaz que proporcione acceso a los valores de configuración por nombre, y obtener los valores que necesita del cuerpo del constructor.


Me gusta la solución de Daniel; sin embargo, solo una cosa que veo es el estrecho acoplamiento de nombres de parámetros entre el actor (que crea CompopositionContrainer ()) y Exportar parte con [ImportingConstructor] para CTOR personalizado. Por ejemplo, "Método" tiene dos correspondencias en ambos lugares. Hace difícil mantener la parte Exportar si el actor y la parte Exportar están en proyectos diferenciados.

Si es posible, agregaría el segundo CTOR a la clase de parte Exportar. Por ejemplo:

[Export(typeof(BUsers))] public class EditProfile : BUsers { [ImportingConstructor] public EditProfile(EditProfileParameters ctorPars) : this(ctorPars.Method, ctorPars.Version) {} public EditProfile(string Method, string Version) { Version = "2"; Action = "Edit"; TypeName = "EditProfile"; }

La clase de EditProfileParameters debería ser sencilla: dos propiedades de Method y Version:

[Export] public class EditProfileParameters{ public string Method { get; set; } public string Version { get; set; } }

El punto clave es agregar el atributo Exportar a la clase. Entonces MEF debería poder asignar esta clase al parámetro de CTOR de EditProfile.

Aquí hay un ejemplo para agregar la parte de exportación al contenedor:

var container = new CompositionContainer(catalog); var instance1 = new EditProfileParameters(); // set property values from config or other resources container.ComposeExportedValue(instance1); container.ComposeParts(this);