您可以将元数据与您的班级一起导出,这是一个示例:
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);
}
}
鉴于该合约和那些示例实现,我们可以将类型导出为Lazy<T, TMetadata>,从而我们可以定义元数据合约:
public interface INamedMetadata
{
string Name { get; }
}
您无需担心创建元数据的实现,因为 MEF 会将任何ExportMetadata 属性值投影为TMetadata 的具体实现,在我们的示例中为INamedMetadata。通过以上,我可以创建以下示例:
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();
}
}
在那个示例类中,我导入了许多实例,例如 Lazy<ILogger, INamedMetadata> 实例。使用Lazy<T,TMetadata> 允许我们在访问值之前访问元数据。在上面的示例中,我使用name 参数来选择要使用的适当记录器。
如果在导入时实例化类是不正确的,您可以使用ExportFactory<T,TMetadata>,它允许您按需启动类型的实例。 (ExportFactory 包含在 Silverlight 版本的 .NET 4.0 中,但 Glenn Block 确实抛出了源代码 on codeplex 供桌面/Web 使用。
希望对你有帮助。