Pregunta

Estoy tratando de encontrar la inyección de constructor de atributos del MEF. No tengo ni idea de cómo lo cuento para cargar los parámetros del constructor.

Esta es la propiedad que estoy tratando de cargar

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

Este es el código que estoy usando para importar las asambleas.

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

Esta es 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";
    }
¿Fue útil?

Solución

Cuando se utiliza el atributo ImportingConstructor, los parámetros del constructor se convierten en las importaciones. De manera predeterminada, lo que va a importar (el nombre de contrato) se basa en el tipo de parámetro o propiedad que está importando en su. Así que en este caso el tipo de contrato, tanto para sus importaciones es una cadena, y no hay ninguna diferencia real entre el primer y el segundo parámetro.

Parece que está intentando utilizar las importaciones para abastecer a los valores de configuración, que no es necesariamente lo que fue diseñado. Para conseguir que haga lo que quiere, debe reemplazar el nombre de contrato para cada uno de los parámetros, así:

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

A continuación, necesita las exportaciones para el Método y la versión en su contenedor. Una forma de hacer esto es sólo para añadirlas 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 definida en la clase AttributedModelServices estática.)

Si desea leer estos valores desde un archivo de configuración de algún tipo, puede crear su propio proveedor de exportación que lee la configuración y proporciona los valores en ella como las exportaciones a los contenedores.

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

Otros consejos

Me gusta la solución de Daniel; Sin embargo, sólo una cosa que veo es la estrecha conexión entre los nombres de parámetros entre el actor (que crea CompopositionContrainer ()) y la parte de exportación con [ImportingConstructor] para CTOR personalizado. Por ejemplo, "Método" tiene dos ser igualada en ambos lugares. Se hace difícil mantener la parte de exportación si el actor y exportación son parte en proyectos de diferencia.

Si es posible, me gustaría añadir el segundo CTOR a la clase parte de exportación. 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 debe ser sencillo: dos propiedades del método y la Version:

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

El punto clave es añadir el atributo de exportación a la clase. Entonces MEF debería ser capaz de mapa de esta clase para el parámetro de CTOR de EditProfile.

Aquí es ejemplo para añadir la parte de exportación de contenedores:

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

Aunque tarde al juego, aquí hay otro enfoque que aprovecha una característica menos conocida de MEF: Las exportaciones de Propiedad

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 para usos ObjectMother para que esto funcione, y no se requieren atributos en EditProfile.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top