如何从MEF的多个零件中导入特定零件? [英] How to import specific part from multi parts in MEF?
问题描述
我将MEF用作DI容器,问题是我想从多个零件中导入特定零件.
I am using MEF as DI container and the problem is that I want to import specific part from multiple parts.
例如,我有以下代码:
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
有什么解决办法吗?
预先感谢
推荐答案
您可以将类中的元数据导出,下面是一个示例:
You can export metadata with your class, here's an example:
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>
,从而可以定义元数据合同:
Given that contract and those example implementations, we can import out types as Lazy<T, TMetadata>
whereby we can define a metadata contract:
public interface INamedMetadata
{
string Name { get; }
}
您不必担心创建元数据的实现,因为MEF会将任何ExportMetadata
属性值投影为TMetadata
的具体实现,在我们的示例中为INamedMetadata
.有了以上内容,我可以创建以下示例:
You don't need to worry about creating an implementation of the metadata, as MEF will project any ExportMetadata
attribute values as concrete implementation of TMetadata
, which in our example is INamedMetadata
. With the above, I can create the following example:
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
参数选择要使用的适当记录器.
In that sample class, I am importing many instances, as Lazy<ILogger, INamedMetadata>
instances. Using Lazy<T,TMetadata>
allows us to access the metadata before accessing the value. In the example above, I'm using the name
argument to select the appropriate logger to use.
如果在导入时实例化类是不合适的,则可以使用ExportFactory<T,TMetadata>
,它允许您按需启动类型实例. (ExportFactory
包含在.NET 4.0的Silverlight版本中,但是Glenn Block确实抛出了源代码.
If it is not right to instantiate the class on import, you can use an ExportFactory<T,TMetadata>
which allows you to spin up instances of your types on demand. (ExportFactory
is included in the Silverlight version of .NET 4.0, but Glenn Block did throw the source code on codeplex for Desktop/Web use.
我希望能帮上忙.
这篇关于如何从MEF的多个零件中导入特定零件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!