另一种不破坏打开/关闭原则的方法是为每种类型的 StockItem 创建视图模型和视图,然后有一个类型来整理所有暴露的子类型及其对应的视图模型,并提供一个工厂方法接受一个 StockItem 并返回匹配的视图模型。
例如,使用 IoC 容器或 MEF 很容易做到这一点。
更新
作为使用 MEF 的快速示例:
public class StockItemEditViewModelFactory : IPartImportsSatisfiedNotification
{
private Dictionary<Type, IStockItemEditViewModelResolver> resolvers;
[ImportMany(IStockItemEditViewModelResolver)]
private IEnumerable<IStockItemEditViewModelResolver> importedResolvers;
public void OnImportsSatisfied()
{
// Build dictionary of StockItem -> StockItemEditViewModel
// Do error handling if no imported resolvers or duplicate types
resolvers = new Dictionary<Type, IStockItemEditViewModelResolver>
foreach(var importedResolver in importedResolvers)
{
resolvers.Add(importedResolver.StockItemType, importedResolver);
}
}
public IStockItemEditViewModel Create(StockItem stockItem)
{
// Find the appropriate resolver based on stockItem.GetType(), handle errors
var type = stockItem.GetType();
var entry = this.resolvers.FirstOrDefault(kv => kv.Key == type);
var resolver = entry.Value;
return resolver.CreateEditViewModel(stockItem);
}
}
[InheritedExport]
public interface IStockItemEditViewModelResolver
{
Type StockItemType { get; }
IStockItemEditViewModel CreateEditViewModel(StockItem stockItem);
}
public class LotItemEditViewModelResolver : IStockItemEditViewModelResolver
{
Type StockItemType { get { return typeof(LotItem); } }
IStockItemEditViewModel CreateEditViewModel(StockItem stockItem)
{
return new LotItemEditViewModel(stockItem);
}
}
public class MainViewModel
{
public IStockItemEditViewModel ActiveItem { get; private set; }
public MainViewModel(StockItemEditViewModelFactory editViewModelfactory)
{
StockItem stockItem = new LotItem();
this.ActiveItem = editViewModelFactory.Create(myStockItem);
}
}
这是未经测试的,但它向您展示了一般方法。你可以使用泛型来使这个更整洁。
如果您想使用 Unity 而不是 MEF,那么概念将是相同的,但是您需要注册 IStockItemEditViewModelResolver 的每个实现(或使用 Unity 扩展并使用约定),然后您的工厂需要参考容器,以便它可以执行 ResolveAll(请参阅Unity Resolve Multiple Classes)。