4

背景

我喜欢Jeffrey Palermo 的洋葱架构模型(类似于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;}
    }
}

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

  • UI 团队假设想要添加几个数据验证属性和自定义 JSON 序列化属性。
  • 基础架构团队假设想要添加 XML 序列化属性和来自 3rd 方数据库实现的一些自定义属性。
  • 公共 API 团队假设想要添加 WCF 属性。

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

而且这种情况变得更加复杂,因为我自己使用了第 3 方“域模型”(在这种情况下,使用 Google 的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 并发现了一些类似的问题,但没有一个问题能达到我正在寻找的全部范围:

4

1 回答 1

2

您可以使用这些选项来简化工作:

  • 元数据类
  • 对象到对象映射器
  • 代码生成

元数据类

您可以创建元数据类并向这些元数据类添加数据注释和验证属性等属性,然后使用AssociatedMetadataTypeTypeDescriptionProvider. 这样的元数据类只是属性容器,并且使用类型描述符机制将属性添加到您的主类。

例如,您可以通过这种方式为您的模型注册一个元数据类,并让所有受益的基础设施TypeDescriptor看到您的模型的元数据属性:

var provider = new AssociatedMetadataTypeTypeDescriptionProvider(typeof(Model), 
                                                                 typeof(ModelMetadata));
TypeDescriptor.AddProvider(provider, typeof(Model));

对象到对象映射器

您可以在不同的层中拥有视图模型、业务模型和域模型,并使用每个层所需的属性来装饰它们,然后使用对象到对象映射器来AutoMapper简化将这些类相互映射的任务。

AutoMapper 是一个对象-对象映射器。对象-对象映射通过将一种类型的输入对象转换为不同类型的输出对象来工作。AutoMapper 的有趣之处在于,它提供了一些有趣的约定来解决如何将类型 A 映射到类型 B 的繁琐工作。只要类型 B 遵循 AutoMapper 的既定约定,映射两种类型几乎需要零配置。

代码生成

您可以使用一些代码生成工具更轻松地创建元数据类或视图模型类。例如,您可以简单地使用像T4 模板这样的代码生成机制来创建包装类。

在 Visual Studio 中,T4 文本模板是文本块和可以生成文本文件的控制逻辑的混合体。控制逻辑以 Visual C# 或 Visual Basic 中的程序代码片段的形式编写。生成的文件可以是任何类型的文本,例如网页、资源文件或任何语言的程序源代码。

于 2016-01-15T21:39:21.517 回答