Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何创建所需的字段值对象_C#_Domain Driven Design_Nullable_Value Objects - Fatal编程技术网

C# 如何创建所需的字段值对象

C# 如何创建所需的字段值对象,c#,domain-driven-design,nullable,value-objects,C#,Domain Driven Design,Nullable,Value Objects,我正在尝试创建一个必需的字段值对象类,该类将在域模型中的实体之间重用。我还在学习C#语法(一直在VB.net中编码)。我是DDD的新手(但至少读过几本书) 我的目标是设计一个名为RequiredField的值对象,它可以接受几乎任何对象(例如值类型、引用类型或可空值类型(int、string、int?),然后在允许它成为实体状态的一部分之前对其进行验证。每当我的实体有一个必填字段(例如id、主键、名称或任何其他被认为是拥有有效实体所必需的状态)时,我都会使用这个值对象。因此,只要我有一个简单的数

我正在尝试创建一个必需的字段值对象类,该类将在域模型中的实体之间重用。我还在学习C#语法(一直在VB.net中编码)。我是DDD的新手(但至少读过几本书)

我的目标是设计一个名为
RequiredField
的值对象,它可以接受几乎任何对象(例如值类型、引用类型或可空值类型(int、string、int?),然后在允许它成为实体状态的一部分之前对其进行验证。每当我的实体有一个必填字段(例如id、主键、名称或任何其他被认为是拥有有效实体所必需的状态)时,我都会使用这个值对象。因此,只要我有一个简单的数据段,为了拥有一个有效的实体,该实体就会将属性定义为
RequiredField

所以我一直在摆弄这门课,我离它越来越近了,但似乎每次我认为我已经掌握了它,我就遇到了另一个绊脚石。以下是我希望从实体类中看到的用法:

公共类人格
{
公共RequiredField ID{get;private set;}
public RequiredField Name{get;private set;}
public required字段DOB{get;private set;}
//定义其他非必需的属性。。。
公众人格(PersonDTO)
{
ID=新的必填字段(dto.ID);
名称=新的必填字段(dto.Name);
DOB=新的必填字段(dto.DOB);
//设置其他非必需的属性。。。
}
}
用于构造实体的相应DTO(在存储库中创建,或从UI或Web服务等创建应用程序服务):

public class PersonDTO
{
公共long?ID{get;set;}
公共字符串名称{get;set;}
公共日期时间?DOB{get;set;}
}
请注意,我真的希望DTO只是一个数据包(这基本上就是DTO的全部正确吗?)。如果我不允许在这里使用可为null的类型,那么我必须在其他地方进行验证,关键是让实体中的值对象完成这项工作(对吗?)

最后,这里是我到目前为止关于
RequiredField
类的内容。请注意,此代码不会编译

公共类必填字段
{
私人T_值;
公共价值
{
获取{返回_值;}
设置
{
//处理空字符串的特殊情况:
if(typeof(T)=typeof(string)&&string.IsNullOrWhiteSpace((string)值))
//但(字符串)值不起作用:“无法将类型“t”转换为“string”
{
抛出新ArgumentException(“必须提供必需的字符串”);
}
else if(值==null)
{
抛出新ArgumentException(“必须提供必填字段”);
}
//还需要处理Nullable,但不知道如何处理
else if(null.getUnderlineType(typeof(T))!=null)
//需要检查值,而不是T
{
抛出新ArgumentException(“必须提供必填字段”);
}
_价值=价值;
}
}
公共必填字段(T值)
{
价值=价值;
}
//下面是接受可为null的值的失败尝试的开始
//我不喜欢在这里和二传中进行验证
公共RequiredField(对象值)
{
如果(!value.HasValue)
{
抛出新ArgumentException(“必须提供必填字段”);
}
值=值。值;
}
}

所以我把自己弄得一团糟,我开始怀疑我是否在尝试做正确的事情。但是如果我有一个好的开始,是什么让我越过了终点线呢?

我建议利用现有的验证输入的方法,而不是滚动您自己的RequiredValue类型

一些选择:

  • 构造函数中的Guard子句。如果你想在这里提供帮助,你可以使用图书馆
  • 基于属性-“必需”属性,例如
  • 更复杂的逻辑可以封装为

  • 我建议利用现有的验证输入的方法,而不是滚动您自己的RequiredValue类型

    一些选择:

  • 构造函数中的Guard子句。如果你想在这里提供帮助,你可以使用图书馆
  • 基于属性-“必需”属性,例如
  • 更复杂的逻辑可以封装为

  • 好的,多亏了一些正确方向的推动,以及解决方案的帮助,我想出了自己的解决方案。它可能会更漂亮一点,但它完成了任务(到目前为止通过了我所有的单元测试!)

    最后我不得不把输入值框起来。如果有一种不用拳击的方法,我肯定仍然对更清洁的解决方案感兴趣

    公共类必填字段
    {
    私人T_值;
    公共RequiredField(IConvertible值)
    {
    设置值(值);
    }
    公共T GetValue()
    {
    返回_值;
    }
    公共void设置值(IConvertible值)
    {
    类型t=类型(t);
    类型u=可空。GetUnderlineType(t);
    如果(值==null)
    {
    //引用对象为空
    抛出新ArgumentException(“必须提供必填字段”);
    }
    else if(值为string&&string.IsNullOrWhiteSpace(Convert.ToString(值)))
    {
    //字符串为null、空或空白
    抛出新ArgumentException(“必须提供必填字段”);
    }
    如果(u!=null),则为else
    {
    如果(值==null)
    {
    //可为null的对象为null
    抛出新ArgumentException(“必须提供必填字段”);
    }
    
    public RequiredField<DateTime> DOB { get; private set; }
    
    public PersonEntity(PersonDTO dto)
    {
        ID = new Identifier(dto.EY);
        Name = new Name(dto.EID);
        DOB = new DateOfBirth(dto.DOB);
        // set other non-required properties ...
    }
    
    // constructors
    new Value(...)
    
    // factory methods
    Value.of(...)
    Value.from(...)
    
    // Factories
    api.newInstance(...)
    
    // Builder
    api.newBuilder()....build()
    
    interface OpaqueValue extends ICanEqual {...}
    
    interface Whatzit {
        interface Identity extends OpaqueValue {...}
    }
    
    interface Whoozit {
        interface Identity extends OpaqueValue {...}
    }
    
    // CompileTimeError
    Whatzit.Identifier target = source.getWhatzit().id