有两种方法可以做你想做的事情:
- 创建一个工厂并将所有必要的部分导入工厂,然后将其传递给类的构造函数。为此,您必须让您的工厂了解实现
IBarViewModel
接口的不同类以及它们实例化所需的部分,或者使用反射将它们放在某个列表中。
BarViewModelFactory:
[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;
}
}
IBarViewModel 实现:
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; }
}
BarViewModelFactory:
[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;
}
}
IBarViewModel 实现:
[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; }
}
对于这两种情况,我选择使用字符串文本来区分SuperBarViewModel
("x") 和BarViewModel
(""),但您实际上可以选择任何您想要帮助选择的元数据。
使用示例(适用于两种情况):
[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...
}
}
显然,您可以在此基础上做更多事情,例如创建自己的自定义ExportAttribute
,而不是使用默认ExportMetadataAttribute
导出元数据。这将允许您创建更复杂的元数据。此外,如果需要, SatisfyImports
/是需要研究的东西。SatisfyImportsOnce
基本上,您可以扩展此答案以自定义您的解决方案。