【发布时间】:2018-04-17 22:14:26
【问题描述】:
此处为简化报告示例:
假设我有三个不同的值对象,它们都有一个 ID 属性:
public class ObjectA() { int ID { get; set; } }
public class ObjectB() { int ID { get; set; } }
public class ObjectC() { int ID { get; set; } }
假设我想使用来自 URL 的“ClassTypePlusID”参数,如下所示:
http://www.example.com/show/A1
http://www.example.com/show/B3
http://www.example.com/show/C2
现在,在我的视图模型中,提取类型(A、B 或 C)和 ID(1、3 或 2)非常容易。从那里开始,水合一个值对象并不难(简化,没有错误处理):
public object GetValueObject(string ClassTypePlusID)
{
var type = ClassTypePlusID.Substring(0, 1);
int.TryParse(ClassTypePlusID.Substring(1, 1), out var id);
if (type == "A")
{
return new ValueObjectA() { ID = id };
}
else if (type == "B")
{
return new ValueObjectB() { ID = id };
}
else if (type == "C")
{
return new ValueObjectC() { ID = id };
}
}
然后,我有三个 GetData() 方法来获取与对象相关的数据(同样,这里大大简化了):
private void GetData(ValueObjectA A)
{
// SELECT * FROM TableA WHERE ID=A.ID
}
private void GetData(ValueObjectB B)
{
// SELECT * FROM TableB WHERE ID=B.ID
}
private void GetData(ValueObjectC C)
{
// SELECT * FROM TableC WHERE ID=C.ID
}
所以最后,我们找到了痛苦的根源......现在我需要将该值对象提供给一个方法。但是我必须将对象(重新)转换为正确的类型,然后才能将其用作参数。我不能这样做:
var valueObject = GetValueObject(urlParameter);
GetData(valueObject);
编译器(我想这是正确的)无法从对象转换为 ObjectA、ObjectB 或 ObjectC。所以我必须为它做这种可笑的扭曲:
var valueObject = GetValueObject("A1");
if (valueObject is ObjectA)
{
GetData((ValueObjectA)valueObject);
}
else if (valueObject is ObjectB)
{
GetData((ValueObjectB)valueObject);
}
else if (valueObject is ObjectC)
{
GetData((ValueObjectC)valueObject);
}
为了雪上加霜,我还没有完成 if 语句,因为我必须在视图中再次使用它们才能显示数据对象(无论它可能是哪个)。
所以我一直在追赶我的尾巴,试图弄清楚如何在没有所有丑陋(且难以维护)的 if 语句的情况下做到这一点。必须有一种 OOP 方式来做到这一点,但我正在努力弄清楚它是什么。
编辑:好的,正如我所想,第一个建议是使用继承。所以让我试试,也许你能告诉我我错过了什么。
我确实了解继承和多态的基础知识,但我仍在学习如何有效地使用它们(如您所见)...
因此,如果我要使用继承,我需要有一个抽象类,该类在要进行继承的对象之间具有共同的属性/行为。我看不出有什么共同点。我在示例中展示的GetData 方法将利用特定于对象的存储库,并在 ViewModel 中返回(或存储)一个 DTO,以便 View 可以访问它。因此,该方法的输入不常见(它将是三个值对象之一),并且该方法的输出也不常见(它将是包含相应表中数据的三个不同 DTO 之一) .
我并不是说继承或多态不是答案(我敢肯定),我只是不知道如何利用它。
编辑#2:在我试图简化问题时,我可能走得太远了。为移动目标道歉,并且第一次没有正确表达我的问题,这不是我的意图。
在最初的问题中,我试图推断 ObjectA、B 和 C 是实际值对象(每个 DDD),但我从未明确表示过。所以我现在说,我更新了示例代码,希望能更好地加强这一点。
将GetData 方法移动到值对象中存在一些问题。首先,我认为它不属于那里。 ValueObject 的目的是描述特定类型的 ID。它在我的域中的多个实体中使用。另一个问题是GetData 方法在我的示例中被简化了(可能太多了),它实际上有额外的 ID 参数进入它(也从 URL 中提取)。从那里,GetData 方法将利用各种存储库来用它需要的数据(来自多个数据集)填充视图模型。所以这里的底线是我在这里的应用程序服务层。而且我不相信GetData 方法属于领域层的值对象内部。
希望这可以更好地阐明问题/问题(但我觉得我当然可以做得更好,如果我有任何想法,我会继续思考并更新)。
【问题讨论】:
-
你熟悉继承吗?您的 A、B 和 C 对象可以从单个抽象基类继承吗?级联
if是一个经典问题,继承可以很好地解决。 -
在原始问题中添加了一些措辞......如果有共同的属性/行为,我没有看到它(或在错误的地方寻找它)。
标签: c# asp.net-mvc oop