我喜欢Jeffrey Palermo's Onion Architecture模型(类似于Hexagonal Architecture),它规定域模型位于“中心”和基础架构的具体实现,特别是具体的存储库位于外围。
所以说我有一个域模型:
//https://libphonenumber.codeplex.com/
using libphonenumber;
namespace MyApplication.Domain
{
public class Speaker
{
public virtual string Name {get;set;}
public virtual PhoneNumber PhoneNumber {get;set;}
}
}
现在我需要将此域模型公开给其他团队:
我不想让每个团队全权委托将属性添加到我的域模型 中,我特别不希望他们添加所有他们的“特定于图层”依赖于我的模型程序集。
这个案子变得更加复杂,因为我自己使用第三方“域名模型”(在这种情况下使用谷歌的LibPhoneNumber处理电话号码)。
理想情况下,他们每个人都需要创建自己的包装类,如:
using MyApplication.Domain;
namespace MyApplication.UI.DomainWrappers
{
public class UISpeaker
{
private Speaker _speaker;
public class UISpeaker(Speaker speaker = null)
{
_speaker = speaker ?? new Speaker();
}
[Required]
public virtual string Name {
get{ return _speaker.Name; }
set{ _speaker.Name = value; }
}
[Required]
public virtual PhoneNumber PhoneNumber {
get{ return _speaker.PhoneNumber ; }
set{ _speaker.PhoneNumber = value; }
}
//Conversion operators
public static implicit operator UISpeaker(Speaker s)
{
return new UISpeaker(s);
}
public static implicit operator Speaker(UISpeaker s)
{
return s._speaker;
}
}
}
编写和维护UISpeaker
类是一个痛苦而且无聊的样板代码。
是否有更好的方式添加属性每个团队想要添加而不让他们直接编辑域模型?或者是否有一些工具可以帮助生成这些包装类(我可能正在考虑像Fody或T4 Templates这样的编织工具,但我对这两者都不熟悉知道他们是否可以在这个用例中提供帮助。)
我环顾了Stackoverflow,发现了一些类似的问题,但没有一个能达到我想要的全部范围:
Avoid using the JsonIgnore attribute in a domain model - 最后只使用域模型上的.NET本机属性,因此您不必依赖Json.Net
< / LI> Add an attribute to another assembly's class - 使用CustomReflectionContext
向现有类型添加属性进行讨论。这看起来非常酷,但不幸的是,该模型将被移交给第三方代码(ORM,EF,Json.Net等)进行反射,所以我认为这不会起作用。
Having Separate Domain Model and Persistence Model in DDD - 确认每个图层都应该拥有自己的域模型版本,但没有讨论是否有任何工具/策略可以更轻松地编写/维护代码。
答案 0 :(得分:2)
您可以使用这些选项来简化工作:
元数据类
您可以创建元数据类并将数据注释和验证属性等属性添加到这些元数据类,然后使用AssociatedMetadataTypeTypeDescriptionProvider
将这些元数据类与主域类相关联。此类元数据类只是属性容器,使用类型描述符机制向主类添加属性。
例如,您可以通过这种方式为模型注册元数据类,并让所有受益TypeDescriptor
的基础架构看到您的模型的元数据属性:
var provider = new AssociatedMetadataTypeTypeDescriptionProvider(typeof(Model),
typeof(ModelMetadata));
TypeDescriptor.AddProvider(provider, typeof(Model));
对象到对象映射器
您可以在不同的图层中拥有视图模型,业务模型和域模型,并使用每个图层所需的属性来装饰它们,然后使用对象映射器(如AutoMapper
来简化映射这些类的任务彼此。
AutoMapper是一个对象 - 对象映射器。对象 - 对象映射的工作原理 将一种类型的输入对象转换为一种输出对象 不同的类型。 AutoMapper的有趣之处在于它提供了 一些有趣的约定,以肮脏的工作从计算 如何将类型A映射到类型B.只要类型B如下 AutoMapper的既定惯例,几乎为零配置 需要映射两种类型。
代码生成
使用某些代码生成工具,您可以更轻松地创建元数据类或查看模型类。例如,您可以使用像T4 Templates这样的代码生成机制创建包装类。
在Visual Studio中,T4文本模板是文本块和 可以生成文本文件的控制逻辑。控制逻辑是 在Visual C#或Visual Basic中编写为程序代码的片段。该 生成的文件可以是任何类型的文本,例如网页或 资源文件,或任何语言的程序源代码。