C# DDD中的空实体
以产品实体或集合为例,该实体或集合引用了另一个名为类别的实体。在发生像CategorizeProduct这样的域事件之前,类别的状态为空。为了在C#中表示这一点,我必须使用C# DDD中的空实体,c#,null,domain-driven-design,nullable,C#,Null,Domain Driven Design,Nullable,以产品实体或集合为例,该实体或集合引用了另一个名为类别的实体。在发生像CategorizeProduct这样的域事件之前,类别的状态为空。为了在C#中表示这一点,我必须使用NULL。我不能在C#中使用Nullable,因为它只能用于值类型 在DDD中使用NULL是否为反模式?建议的一些解决方案是:(1)使用或(2)使用a代替单个实体 也许是一个选项,但是否有不同的方法来处理DDD中的空实体状态?我理解您的担忧-NULL可能表示尚未加载类别,或者可能表示尚未分配类别 一个选项是添加一个可为空的属性
NULL
。我不能在C#中使用Nullable
,因为它只能用于值类型
在DDD中使用NULL
是否为反模式?建议的一些解决方案是:(1)使用或(2)使用a代替单个实体
也许
是一个选项,但是否有不同的方法来处理DDD中的空实体状态?我理解您的担忧-NULL可能表示尚未加载类别,或者可能表示尚未分配类别
一个选项是添加一个可为空的属性CategoryId,其中包含已分配类别的ID。如果分配了类别,则始终填写ID,否则为空。这意味着,如果填写了CategoryID且Category为空,则分配了一个类别,但未加载该类别
如果您使用实体框架来加载或持久化您的域,那么这种方法自然适合
public class Product
{
public Product()
{
// validate entity
}
public int? CategoryId { get; private set; }
public Category Category { get; private set; }
}
我理解您的担忧-NULL可能表示尚未加载类别,也可能表示尚未分配类别
一个选项是添加一个可为空的属性CategoryId,其中包含已分配类别的ID。如果分配了类别,则始终填写ID,否则为空。这意味着,如果填写了CategoryID且Category为空,则分配了一个类别,但未加载该类别
如果您使用实体框架来加载或持久化您的域,那么这种方法自然适合
public class Product
{
public Product()
{
// validate entity
}
public int? CategoryId { get; private set; }
public Category Category { get; private set; }
}
我理解您的担忧-NULL可能表示尚未加载类别,也可能表示尚未分配类别
一个选项是添加一个可为空的属性CategoryId,其中包含已分配类别的ID。如果分配了类别,则始终填写ID,否则为空。这意味着,如果填写了CategoryID且Category为空,则分配了一个类别,但未加载该类别
如果您使用实体框架来加载或持久化您的域,那么这种方法自然适合
public class Product
{
public Product()
{
// validate entity
}
public int? CategoryId { get; private set; }
public Category Category { get; private set; }
}
我理解您的担忧-NULL可能表示尚未加载类别,也可能表示尚未分配类别
一个选项是添加一个可为空的属性CategoryId,其中包含已分配类别的ID。如果分配了类别,则始终填写ID,否则为空。这意味着,如果填写了CategoryID且Category为空,则分配了一个类别,但未加载该类别
如果您使用实体框架来加载或持久化您的域,那么这种方法自然适合
public class Product
{
public Product()
{
// validate entity
}
public int? CategoryId { get; private set; }
public Category Category { get; private set; }
}
对于这些类型的东西,您可以使用。例如,可以将String.Empty
属性作为一个简单的例子
如果null
对象的某些方法应该具有不同的行为,则可以将其作为一个私有内部类,该类派生自Category
,并重写特定的行为
对于您的类别
:
public class Category
{
private class UnassignedCategory : Category
{
public UnassignedCategory() : base("") { }
}
private static readonly UnassignedCategory _unassigned = new UnassignedCategory();
public static Category Unassigned
{
get { return _unassigned; }
}
public Category(string name)
{
this.Name = name;
}
public string Name { get; private set; }
public bool IsAssigned
{
get { return ReferenceEquals(this, _unassigned); }
}
}
请注意,在上面的示例中,由于Category
上没有默认的无参数构造函数,并且无法更改Name
属性的值,因此实际上不需要子类,我们可以简单地使用静态Category
实例
用法:
public class Product
{
public Product()
{
Category = Category.Unassigned;
// other stuff
}
// other stuff.
public void AssignCategory(Category category)
{
// Any associated logic.
Category = category;
}
public Category Category { get; private set; }
}
如果您正在从数据库中保存和加载null
(即未分配)类别,您可能希望在此主题上使用一个变体,带有“未分配”的显式(不可变)id/属性,该id/属性与其他类别
属性一起保存,并在IsAssigned
检查中使用
可行的替代方案
一个完全可行的替代方法是使用null
引用继续做您现在正在做的事情。如果需要,您可以添加一些扩展方法,使您的生活更轻松
public static MyCategoryExtensions
{
public static bool IsNullOrEmpty(this Category category)
{
return category == null || string.IsNullOrEmpty(category.Name);
}
public static Category EmptyIfNull(this Category category)
{
return category ?? new Category("");
}
public static Category DefaultIfNullOrEmpty(this Category category)
{
return category.IsNullOrEmpty()
? new Category(Category.DefaultName)
: category;
}
}
对于这些类型的东西,您可以使用。例如,可以将String.Empty
属性作为一个简单的例子
如果null
对象的某些方法应该具有不同的行为,则可以将其作为一个私有内部类,该类派生自Category
,并重写特定的行为
对于您的类别
:
public class Category
{
private class UnassignedCategory : Category
{
public UnassignedCategory() : base("") { }
}
private static readonly UnassignedCategory _unassigned = new UnassignedCategory();
public static Category Unassigned
{
get { return _unassigned; }
}
public Category(string name)
{
this.Name = name;
}
public string Name { get; private set; }
public bool IsAssigned
{
get { return ReferenceEquals(this, _unassigned); }
}
}
请注意,在上面的示例中,由于Category
上没有默认的无参数构造函数,并且无法更改Name
属性的值,因此实际上不需要子类,我们可以简单地使用静态Category
实例
用法:
public class Product
{
public Product()
{
Category = Category.Unassigned;
// other stuff
}
// other stuff.
public void AssignCategory(Category category)
{
// Any associated logic.
Category = category;
}
public Category Category { get; private set; }
}
如果您正在从数据库中保存和加载null
(即未分配)类别,您可能希望在此主题上使用一个变体,带有“未分配”的显式(不可变)id/属性,该id/属性与其他类别
属性一起保存,并在IsAssigned
检查中使用
可行的替代方案
一个完全可行的替代方法是使用null
引用继续做您现在正在做的事情。如果需要,您可以添加一些扩展方法,使您的生活更轻松
public static MyCategoryExtensions
{
public static bool IsNullOrEmpty(this Category category)
{
return category == null || string.IsNullOrEmpty(category.Name);
}
public static Category EmptyIfNull(this Category category)
{
return category ?? new Category("");
}
public static Category DefaultIfNullOrEmpty(this Category category)
{
return category.IsNullOrEmpty()
? new Category(Category.DefaultName)
: category;
}
}
对于这些类型的东西,您可以使用。例如,可以将String.Empty
属性作为一个简单的例子
如果null
对象的某些方法应该具有不同的行为,则可以将其作为一个私有内部类,该类派生自Category
,并重写特定的行为
对于您的类别
:
public class Category
{
private class UnassignedCategory : Category
{
public UnassignedCategory() : base("") { }
}
private static readonly UnassignedCategory _unassigned = new UnassignedCategory();
public static Category Unassigned
{
get { return _unassigned; }
}
public Category(string name)
{
this.Name = name;
}
public string Name { get; private set; }
public bool IsAssigned
{
get { return ReferenceEquals(this, _unassigned); }
}
}
请注意,在上面的示例中,由于Category
上没有默认的无参数构造函数,并且无法更改Name
属性的值,因此实际上不需要子类,我们可以简单地使用静态Category
实例
用法: