适当的架构:在.NET中为域模型添加属性

时间:2016-01-15 20:33:08

标签: c# architecture domain-model onion-architecture fody

背景

我喜欢Jeffrey Palermo's Onion Architecture模型(类似于Hexagonal Architecture),它规定域模型位于“中心”和基础架构的具体实现,特别是具体的存储库位于外围。

enter image description here

所以说我有一个域模型

//https://libphonenumber.codeplex.com/
using libphonenumber;

namespace MyApplication.Domain
{
    public class Speaker
    {
         public virtual string Name {get;set;}
         public virtual PhoneNumber PhoneNumber {get;set;}
    }
}

现在我需要将此域模型公开给其他团队:

  • UI团队假设要添加多个数据验证属性和自定义JSON序列化属性。
  • 基础架构小组假设要从第三方数据库实施中添加XML序列化属性和一些自定义属性。
  • 公共API团队假设要添加WCF属性。

我不想让每个团队全权委托将属性添加到我的域模型 中,我特别不希望他们添加所有他们的“特定于图层”依赖于我的模型程序集

这个案子变得更加复杂,因为我自己使用第三方“域名模型”(在这种情况下使用谷歌的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类是一个痛苦而且无聊的样板代码。

是否有更好的方式添加属性每个团队想要添加而不让他们直接编辑域模型?或者是否有一些工具可以帮助生成这些包装类(我可能正在考虑像FodyT4 Templates这样的编织工具,但我对这两者都不熟悉知道他们是否可以在这个用例中提供帮助。)

研究

我环顾了Stackoverflow,发现了一些类似的问题,但没有一个能达到我想要的全部范围:

1 个答案:

答案 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中编写为程序代码的片段。该   生成的文件可以是任何类型的文本,例如网页或   资源文件,或任何语言的程序源代码。