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.
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
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