我正在处理的当前WPF项目需要一个复杂业务对象的查看器/编辑器。
首先,业务对象是“通用的”,因为它几乎没有继承 - 它们使用相同的底层域模型,但由于其(嵌套)属性的值,它们是不同的。
例如,假设业务对象是衍生,衍生有大量其他嵌套业务对象,其中一个是 Legs的集合。
Leg 的 PROPERTIES 确定实际的 Derivative 。请记住,所有业务对象都是“包罗万象”(One Leg类,而不是LegA扩展基类LegBase。)
所以说“Derivative X”由两条腿组成, BOTH 的类型为 Leg 。一个人有一个属性说LegType = LegAFunding,第二个腿有LegType = CallableBlahh。
问题是不同的 Derivatives 需要不同的屏幕,但它们可能有相同的Legs,目的是你看不到某些类型的某些属性,而对于其他人你需要一些特殊的属性等。
是否存在构建或解析视图模型的“通用”模式,以便在明天发布新的Derivative时,我们可以使用构建器或工厂为其解析视图模型?有一个我们可以解决的默认视图模型会很棒,如果需要,我们可以扩展一个包含我们需要的基本属性集的正确视图模型,添加我们想要绑定/编辑/查看的额外属性,并合并它进入建筑商或工厂;该新衍生产品的视图将在视图模型中具有额外属性。
这是关于构建视图模型的一种控制反转,但我们的解决策略很复杂,并且对于我们正在解决的各种视图模型会有所不同。
有什么想法吗? This Webpage将这些类型的概念描述为“对象池”和“身份地图”等,但我找不到关于这些概念的任何信息,除了他们在该网站上的模糊想法和描述。
public interface IViewModelFactoryProvider
{
// TBVM is the base view model you want and TM is the model you're 'wrapping'
IViewModelFactory<TBVM, TM> GetViewModelFactory<TBVM, TM>()
where TBVM : IViewModelBase;
}
public class ViewModelFactoryProvider
: IViewModelFactoryProvider
{
private readonly IUnityContainer container;
public ViewModelFactoryProvider(IUnityContainer container)
{
this.container = container;
RegisterFactories(container);
}
private static void RegisterFactories(IUnityContainer container)
{
container.RegisterType<IViewModelFactory<LegSummaryViewModel, Leg>, LegSummaryViewModelFactory>();
// etc...
}
public IViewModelFactory<TBVM, TM> GetViewModelFactory<TBVM, TM>()
where TBVM : IViewModelBase
{
// abstract away resolution from container
return container.Resolve<IViewModelFactory<TBVM, TM>>();
}
}
public class FundingLegSummaryViewModelFactory
: BaseViewModelFactory<FundingLegSummaryViewModel, Leg>
{
public FundingLegSummaryViewModelFactory(IUnityContainer container)
: base(container)
{
}
public override FundingLegSummaryViewModel CreateViewModel(Derivative deriv, Leg model)
{
var legType = model.LegType;
switch (legType)
{
/*
case "ThisFundingLegType":
return container.Resolve<ThisFundingLegTypeSummaryViewModel>(new ResolverOverride[]
{
new ParameterOverride("deriv", deriv)
});
*/
// I always have a default, new derivative, no problem...
default:
return container.Resolve<FundingLegSummaryViewModel>(new ResolverOverride[]
{
new ParameterOverride("deriv", deriv)
});
}
}
}
foreach (var leg in model.Legs)
{
// I want a LegSummaryViewModel, don't care which one...the factory should resolve it for me...There is another LegSummaryViewModelFactory that based on one property uses a specific leg factory, above you see FundingLegSummaryViewModelFactory as one of these.
var legSummaryViewModel = viewModelFactoryProvider
.GetViewModelFactory<LegSummaryViewModel, Leg>()
.CreateViewModel(model, leg);
LegSummaries.Add(legSummaryViewModel);
}
请注意,我认为这是过度设计,或者更确切地说,使用Unity / DI可以做得更好。也许有一个enum / enum-strings,容器可以在某个地方引导,每个viewmodel类型(Derivative,Leg,Details,so)都可以像这样注册:
container.RegisterType<IViewModelBase, SpecificLegSummaryViewModelForTradeTypeAndLegType>(ViewModelTypes.LegSummaryViewModel);
这可以让我灵活地使用区域(Prism)。
答案 0 :(得分:0)
首先,不要依赖ViewModel作为基础实体。或多或少,WPF中的ViewModel与视图相结合。例如命令等。它将减少模块化。
接下来,你说Leg类是某种通用的,然后我假设它可以很容易地使用接口设计。使用接口作为参数而不是类,因为它将增加模块性。
确保使用界面设计业务逻辑。有了它,无论你正在制作什么样的腿,只要你实现了正确的接口,它就会很好用。考虑使用依赖注入,它将适用于这种情况。
如果你提供一些你的通用Leg类及其衍生物的例子,你可以在这里找到更好的答案甚至是例子。
EDIT1:
现在问题比以前更清楚了。但是,我的假设是你需要根据给定的Leg类的类型创建一个视图模型。我将尝试根据Mark Seeman的抽象工厂模式提供一些示例,基于他的答案here。
首先,解决方案的核心在于AbstractFactory。这里有2种模式: 一个。逻辑在于工厂,它将检查正确的ViewModel返回。湾逻辑在解析器中处理,以返回正确的Factory。但是,我将尝试使用(a。)逻辑提供解决方案。
public class LegVMFactory: ILegVMFactory{
private readonly ILeg leg;
public LegFactory(ILeg _leg){
if(_leg == null) throw new Exception(""); //throw any exception you feel proper here
this.leg = _leg;
}
public ILegViewModel Create(){
if(leg is Leg){
return new LegViewModel();
}
else if(leg is LegV1){
return new LegV1ViewModel();
}
else if(leg is LegV2){
return new LegV2ViewModel();
}
// and so on
}
}
然后用法(简单逻辑):
Leg leg = new Leg();
LegVMFactory legVmFactory = new LegVMFactory(leg);
ILegViewModel legVM = legVmFactory.Create();