C# 模式来创建类型取决于另一个对象类型的新对象?
我有这样的想法:C# 模式来创建类型取决于另一个对象类型的新对象?,c#,design-patterns,C#,Design Patterns,我有这样的想法: interface IProduct { } class ProductA : IProduct { } class ProductB : IProduct { } .... interface IViewModel { } class ProductAViewModel : IViewModel { } class ProductBViewModel : IViewModel { } IViewModel CreateViewModel(IProduct pr
interface IProduct { }
class ProductA : IProduct { }
class ProductB : IProduct { }
....
interface IViewModel { }
class ProductAViewModel : IViewModel { }
class ProductBViewModel : IViewModel { }
IViewModel CreateViewModel(IProduct product)
{
var vmType = Assembly.getTypes().SingleOrDefault(x => x.Name == $"{product.GetType().Name}ViewModel");
// Create instance of vmType and perform mapping of properties between product and vm using reflection based on name convention. Automapper can do this for you as well.
}
现在,我希望能够创建ViewModels的实例,而不知道产品的实际类型:
IProduct prod = new ProductA();
IViewModel vm = someFactoryOrBuilderObject.CreateViewModel(prod);
// real type of vm depends on the product's type
// if prod is ProductA, vm must be ProductAViewModel
...
DisplayViewModel(VM); // working with VM as IViewModel (regardless of it's real type)
目标:
- 必须在运行时解析ViewModel的类型
- 向我的应用程序添加新产品和viewmodels不需要对现有代码进行任何更改
- 创建类似映射(字典)的类型(productTypevmType)。但当我想添加更多产品时,我必须更改此地图
- 在每个产品类中创建一个工厂方法,如GetViewModel()。但这违反了SOLID的SRP
- 创建工厂或建筑商。但是这些模式不能满足我的需求
interface IProduct { }
class ProductA : IProduct { }
class ProductB : IProduct { }
....
interface IViewModel { }
class ProductAViewModel : IViewModel { }
class ProductBViewModel : IViewModel { }
IViewModel CreateViewModel(IProduct product)
{
var vmType = Assembly.getTypes().SingleOrDefault(x => x.Name == $"{product.GetType().Name}ViewModel");
// Create instance of vmType and perform mapping of properties between product and vm using reflection based on name convention. Automapper can do this for you as well.
}
警告:这可能不是一个好的设计模式。 实际上,依赖链应该是
视图
=>视图模型
=>模型
(=>
表示“依赖”)。模型
不应知道任何有关视图模型
的信息(即,通过属性,在下面的代码中)
下面的答案只是对你在问题中提出的要求的一种变通
我认为没有真正“干净”的方法可以做到这一点而不使用反射。但是,我们可以使用反射(使用反射的代价是:)使代码的其余部分变得干净 我现在提出一个使用属性的解决方案 记住:只有当每个
ViewModel
类都有一个公共构造函数,并且该类将一个产品
对象作为参数时,此方法才有效如果不是,Varun的解决方案会更好(在这种情况下,您仍然需要一个映射函数)
要使用它,请在产品
类之前添加一个UseViewModel(typeof(ViewModelForThisProductType))
。比如:
[UseViewModel(typeof(ProductAViewModel))]
class ProductA : IProduct { }
[UseViewModel(typeof(ProductBViewModel))]
class ProductB : IProduct { }
您的ViewModel
类应该如下所示:
class ProductAViewModel : IViewModel {
//You can use both IProduct or the derived type (i.e ProductA) as the constructor param
public ProductAViewModel(ProductA a)
{
}
}
class ProductBViewModel : IViewModel {
public ProductBViewModel(IProduct b)
{
}
}
无论如何,在某些地方,您需要“链接”viewmodel和product。恐怕您是对的:(.我只是想坚持SOLID的OCP。如果你想要一个好的模式,那么你可能想借鉴一下Windows Shell命名空间扩展和Microsoft管理控制台,看看它们在幕后是如何工作的。不管怎样,你提出的设计可能是一个糟糕的设计。当你的模型需要出现在许多不同类型的V中时会发生什么iewModels?我可能有一个
患者
需要同时出现在人口统计视图模型
和处方视图模型
中。很少有一个实体类型与视图模型的比例为1:1。但是,视图和视图模型的情况并非如此。我知道有一些框架可以从虚拟机或虚拟机自动确定Vsa.也许这就是你所想的?我也在想反射,但这是我最不想在我的案例中使用的东西。我想要一些“干净”的架构。@Vladimir所有使用反射的“干净”架构框架和库。我可以看出这有两个错误。1)如果一个模型需要在多个ViewModel中显示,会发生什么情况?模型和虚拟机之间很少有1:1的比例2)您纯粹为了虚拟机的利益而用属性污染模型。在规范数据模型系统中,WCF或网络层可能不关心这些attributes@MickyD我同意这是一个糟糕的设计。视图应该知道它们的视图模型,视图模型应该知道它们的模型,而不是相反。但这正是OP所要求的。我将编辑答案,以表明这不是一个好的设计。这是真的,这是OP要求的,是一个合理的解决方案+1.