2011-01-06 20 views
6

Estoy utilizando MEF como contenedor DI y el problema es que quiero importar partes específicas de varias partes.¿Cómo importar partes específicas de varias partes en MEF?

Por ejemplo, he siguientes códigos:

public interface IService 
{ 
    void Send(); 
} 

[Export(typeof(IService))] 
public class Service : IService 
{ 
    public void Send() 
    { 
     Console.WriteLine("Service.Send"); 
    } 
} 

[Export(typeof(IService))] 
public class FakeService : IService 
{ 
    public void Send() 
    { 
     Console.WriteLine("FakeService.Send"); 
    } 
} 

[Import] 
public IService Service { get; set; } // ---> let's say I want to use FakeService 

¿Hay alguna solución?

Gracias de antemano

Respuesta

13

Puede exportar metadatos con su clase, he aquí un ejemplo:

public interface ILogger 
{ 
    void Log(string message); 
} 

[Export(typeof(ILogger)), ExportMetadata("Name", "Console")] 
public class ConsoleLogger : ILogger 
{ 
    public void Log(string message) 
    { 
    Console.WriteLine(message); 
    } 
} 

[Export(typeof(ILogger)), ExportMetadata("Name", "Debug")] 
public class DebugLogger : ILogger 
{ 
    public void Log(string message) 
    { 
    Debug.Print(message); 
    } 
} 

Dado que los contratos y las implementaciones de ejemplo, podemos importar a cabo tipos como Lazy<T, TMetadata> cual podemos definir un contrato de metadatos:

public interface INamedMetadata 
{ 
    string Name { get; } 
} 

No necesita preocuparse por crear una implementación de los metadatos, ya que MEF proyectará cualquier valor de atributo ExportMetadata como implementación concreta de TMetadata, que en nuestro ejemplo es INamedMetadata. Con lo anterior, puedo crear el siguiente ejemplo:

public class Logger 
{ 
    [ImportMany] 
    public IEnumerable<Lazy<ILogger, INamedMetadata>> Loggers { get; set; } 

    public void Log(string name, string message) 
    { 
    var logger = GetLogger(name); 
    if (logger == null) 
     throw new ArgumentException("No logger exists with name = " + name); 

    logger.Log(message); 
    } 

    private ILogger GetLogger(string name) 
    { 
    return Loggers 
     .Where(l => l.Metadata.Name.Equals(name)) 
     .Select(l => l.Value) 
     .FirstOrDefault(); 
    } 
} 

En esa clase de muestra, Estoy importando muchos casos, como Lazy<ILogger, INamedMetadata> casos. El uso de Lazy<T,TMetadata> nos permite acceder a los metadatos antes de acceder al valor. En el ejemplo anterior, estoy usando el argumento name para seleccionar el registrador apropiado para usar.

Si no es correcto crear una instancia de la clase en la importación, puede usar un ExportFactory<T,TMetadata> que le permite generar instancias de sus tipos bajo demanda. (ExportFactory se incluye en la versión de Silverlight de .NET 4.0, pero Glenn Bloque hicieron lanzar el código fuente para uso on codeplex/Web Desktop.

Espero que ayude.

3

Puede utilizar la sobrecarga de exportación que toma un nombre de contrato así. Luego impórtelo con el nombre del contrato.

[Export("Service", typeof(IService))] 
public class Service : IService { 
} 

[Export("FakeService", typeof(IService))] 
public class FakeService : IService { 
} 

[Import("FakeService")] 
public IService Service { get; set; } 
+0

Gracias Josh, yo estaba tratando de utilizar el nombre de contrato y resolvió mi problema, pero no puedo usar ImportMany si utilizo el nombre del contrato en las partes de exportación. ¿Hay alguna forma de usar ImportMany con Importar partes específicas juntas? – Ray

+0

No realmente. En general, no se puede combinar fácilmente Importación con ImportMany de todos modos Porque si tiene una Importación y hay más de una exportación, tendrá la misma excepción. Sin embargo, podría ImportMany posiblemente en un constructor, luego seleccionar una de las importadas en función de alguna otra lógica. – Josh

0

Puede agregar metadatos de exportación para distinguir las diferentes exportaciones entre sí. Luego, en el lado de la importación, necesitará usar ImportMany y luego filtrarlo en función de los metadatos para encontrar el que desee.

Cuestiones relacionadas