我意识到,MEF在Metro风格的应用程序中受到一定限制。现在不再有容器了,那么我该如何获得特定的导出值,比如ILogger logger = container.GetExportedValues<ILogger>();
?
是否有任何教程介绍MEF的Metro版本?
谢谢帮助, Eny
我意识到,MEF在Metro风格的应用程序中受到一定限制。现在不再有容器了,那么我该如何获得特定的导出值,比如ILogger logger = container.GetExportedValues<ILogger>();
?
是否有任何教程介绍MEF的Metro版本?
谢谢帮助, Eny
public interface IMefTest
{
string Message {get;}
}
[Export(typeof(IMefTest))]
public class MefTest: IMefTest
{
public string Message {get { return "Hello World"; }}
}
接下来,您需要设置CompositionService
(类似于容器,但不完全相同)。我们希望将其设置在可以普遍访问的地方,因为这将是您调用以满足导入的位置(在此之后的代码片段中会更多介绍)。
我将其放在了我的示例项目中的App.xaml.cs文件中:
static System.ComponentModel.Composition.ICompositionService _compositionService = null;
public static System.ComponentModel.Composition.ICompositionService CompositionService
{
get
{
if (_compositionService == null)
((App)App.Current).loadCompositionService();
return _compositionService;
}
}
private void loadCompositionService()
{
// Create a catalog where MEF will search for exported parts to plugin
var catalog = new System.ComponentModel.Composition.Hosting.AssemblyCatalog(GetType().GetTypeInfo().Assembly);
_compositionService = catalog.CreateCompositionService();
}
关于此事的一些小信息。我们已经设置了一个装配目录,这意味着MEF将仅查询此程序集以查找导出的类型。还有其他类型的目录,我相信您应该能够将2个或更多目录组合在一起。
好的,在我的页面中(顺便说一句,我将其构建到了MSDN入门文档中的C# HelloWorld示例中)。
要获取目录中某个部件的实例,您只需要向要获取的类添加属性并添加导入属性即可(还有一些方法可以让它指定构造函数上的参数,但我试图保持简单)。
[Import]
public IMefTest Tester { get; set; }
if(App.CompositionService != null)
App.CompositionService.SatisfyImportsOnce(this);
为确保服务存在而进行的检查是我过于谨慎了,实际上它应该是存在的。
在此步骤之后,您可以在类中实际使用Tester.Message
属性。MEF中还有更多选项。我希望这可以帮助您(如果有帮助,请将我标记为答案,因为我从为客户计费的宝贵时间中抽出了时间来为您完成这项工作)。
我知道您希望简单地调用容器并让它返回某种类型的实例。使用其他形式的MEF可以做到这一点,因此我想它应该也可以在WinRT中实现,但是目前我并不确定。
正如我在评论中所写的那样,我并不是很喜欢这种方法,但目前这是最好的选择:
public class CompositionContainer
{
private readonly CompositionService _service;
public CompositionContainer(CompositionService service)
{
_service = service;
}
public T GetExportedValue<T>()
{
var factoryProvider = new FactoryProvider<T>();
_service.SatisfyImportsOnce(factoryProvider);
return factoryProvider.Factory.CreateExport().Value;
}
private class FactoryProvider<T>
{
[Import]
public ExportFactory<T> Factory;
}
}
而简单的使用案例可能是这样的:
class Program
{
static void Main()
{
var catalog = new ApplicationCatalog();
var container = new CompositionContainer(catalog.CreateCompositionService());
for (int i = 0; i < 5; i++)
{
var dude = container.GetExportedValue<IDude>();
Console.WriteLine(dude.Say());
}
}
public interface IDude
{
string Say();
}
[Export(typeof(IDude))]
public class Eminem : IDude
{
private static int _instanceNo;
private readonly string _phrase;
public Eminem()
{
_instanceNo++;
_phrase = string.Join(" ", Enumerable.Range(0, _instanceNo)
.Select(_ => "yo!"));
}
public string Say()
{
return _phrase;
}
}
}
我现在不关心性能,但我猜以后会添加工厂提供者或工厂的缓存