Parameters MEF+;MVVM:如何使用非导入或混合参数实例化类
我一直在试验MEF和MVVM。我想让MEF使用字符串构造函数参数初始化非共享ViewModel实例,例如:Parameters MEF+;MVVM:如何使用非导入或混合参数实例化类,parameters,constructor,viewmodel,mef,factory,Parameters,Constructor,Viewmodel,Mef,Factory,我一直在试验MEF和MVVM。我想让MEF使用字符串构造函数参数初始化非共享ViewModel实例,例如: // BarViewModel's constructor has one single string parameter IBarViewModel bar = container.GetExportedValue<IBarViewModel>("bar title"); [Export(typeof(IBarViewModelFactory))] public class
// BarViewModel's constructor has one single string parameter
IBarViewModel bar = container.GetExportedValue<IBarViewModel>("bar title");
[Export(typeof(IBarViewModelFactory))]
public class BarViewModelFactory : IBarViewModelFactory
{
[Import]
public Lazy<CompositionContainer> Container { get; set; }
public IBarViewModel CreateBarViewModel(string text)
{
IBarViewModel result = null;
var tempContainer = CreateTemporaryDisposableContainer(Container.Value);
try
{
result = new BarViewModel(text);
tempContainer.ComposeParts(result);
}
catch (Exception ex)
{
}
finally
{
}
return result;
}
现在我不知道如何用MEF实例化这个类。我想这是一种非常常见的情况,所以我想知道MEF是否能够处理这一问题?有两种方法可以完成您希望执行的操作:
- 创建一个工厂并将所有必要的部分导入工厂,然后将其传递给类的构造函数。为此,您必须让工厂了解实现
接口的不同类以及它们实例化所需的部分,或者使用反射将它们放入一些列表中IBarViewModel
- 或者,您可以利用
。它是,和的一部分。请注意,ExportFactory无法实例化类并将参数传递到构造函数中,因此在创建实例后,必须通过设置属性(或调用方法)来使用ExportFactory
文本。还有,这里是一些关于这个项目的信息
对于这两种情况,我都选择使用字符串文本来区分
SuperBarViewModel
(“x”)和BarViewModel
(“”),但实际上您可以选择任何元数据来帮助选择一种
使用示例(适用于两种方案):
显然,除此之外,您还可以做很多事情,例如创建自己的自定义
ExportAttribute
,而不是使用默认的ExportMetadataAttribute
进行元数据导出。这将允许您创建更复杂的元数据。此外,SatisfyImports
/SatisfyImportsOnce
是您需要了解的东西。基本上,您可以在此答案上展开以自定义您的解决方案。MEF在.NET 4.0中,因此不支持开箱即用的ExportFactory。我正在使用格伦港口。谢谢,你的第一个解决方案比我的明显改进。
[Import]
public ILogger Logger {get;set;}
[ImportingConstructor]
public SomeClass(IDataService service, string text)
{
Logger.Trace(text);
}
[Export(typeof(IBarViewModelFactory))]
public class BarViewModelFactory : IBarViewModelFactory
{
[Import] private IServiceA ServiceA { get; set; }
[Import] private IServiceB ServiceB { get; set; }
// val is some metadata value to help decide which class to instantiate.
public IBarViewModel CreateBarViewModel(string val, string text)
{
IBarViewModel result = null;
try
{
// Select using metadata...
if (String.Equals(val, "x", StringComparison.OrdinalIgnoreCase))
result = new SuperBarViewModel(ServiceA, ServiceB, text);
else
result = new BarViewModel(ServiceA, text);
}
catch (Exception ex) { ... }
finally { ... }
return result;
}
}
public sealed class BarViewModel : ViewModelBase, IBarViewModel
{
public BarViewModel(IServiceA svcA, string text)
{
ServiceA = svcA;
// Do something with text, etc...
}
private IServiceA ServiceA { get; set; }
}
public sealed class SuperBarViewModel : ViewModelBase, IBarViewModel
{
public BarViewModel(IServiceA svcA, IServiceB svcB, string text)
{
ServiceA = svcA;
ServiceB = svcB;
// Do something with text, etc...
}
private IServiceA ServiceA { get; set; }
private IServiceB ServiceB { get; set; }
}
[Export(typeof(IBarViewModelFactory))]
public class BarViewModelFactory : IBarViewModelFactory
{
[ImportMany]
private IEnumerable<ExportFactory<IBarViewModel, IBarViewModelMetadata>> Factories { get; set; }
// val is some metadata value to help decide which class to return.
public IBarViewModel CreateBarViewModel(string val, string text)
{
IBarViewModel result = null;
try
{
result = Factories.Single(x => String.Equals(x.Metadata.Value, val, StringComparison.OrdinalIgnoreCase))
.CreateExport()
.Value;
result.Text = text;
}
catch (Exception ex) { ... }
finally { ... }
return result;
}
}
[ExportMetadata(typeof(IBarViewModel, ""))]
public sealed class BarViewModel : ViewModelBase, IBarViewModel
{
[Import] private IServiceA ServiceA { get; set; }
public string Text { get; set; }
}
[ExportMetadata(typeof(IBarViewModel, "x"))]
public sealed class SuperBarViewModel : ViewModelBase, IBarViewModel
{
[Import] private IServiceA ServiceA { get; set; }
[Import] private IServiceB ServiceB { get; set; }
public string Text { get; set; }
}
[Export]
public sealed class SomeClass
{
[Import]
private IBarViewModelFactory BarViewModelFactory { get; set; }
public void SomeMethod()
{
// Get the "Super" version by passing in "x" (metadata).
var barVM = BarViewModelFactory.CreateBarViewModel("x", "my text");
// etc...
}
}