我是一个“老派”程序员,在这里正在努力继承我的优势。我发现自己重复了代码,并开始闻起来。我没有坚持DRY,所以我试图在这里重构一下,以减少代码重复!具体类继承自继承自通用抽象类的抽象类
我试图写在我的实体中使用Value对象类,这将强制执行基本的不变量。我有一个处理平等和哈希像这样一个通用的抽象的ValueObject类:
public abstract class ValueObject<T> where T : ValueObject<T>
{
protected abstract IEnumerable<object> GetEqualityCheckAttributes();
public override bool Equals(object other)
{
return Equals(other as T);
}
public bool Equals(T other)
{
if (other == null)
{
return false;
}
return GetEqualityCheckAttributes().SequenceEqual(other.GetEqualityCheckAttributes());
}
public static bool operator == (ValueObject<T> left, ValueObject<T> right)
{
return Equals(left, right);
}
public static bool operator != (ValueObject<T> left, ValueObject<T> right)
{
return !(left == right);
}
public override int GetHashCode()
{
int hash = 17;
foreach (var obj in this.GetEqualityCheckAttributes())
{
hash = hash * 31 + (obj == null ? 0 : obj.GetHashCode());
}
return hash;
}
}
我一直然后创建我的价值的对象类,然后实现这个抽象类,并提供以确保对象的逻辑不能被创建为无效状态。这是当我开始违反DRY时,并且使用相同的代码创建了许多对象(例如,最大长度为50或30或10的所需字符串)。
所以我希望把强制不变的代码放在它自己的类中,让我的具体值对象类继承那个能力。喜欢的东西(这并不编译,见下文):
public abstract class RequiredStringValueObject : ValueObject<string>
{
private string _value;
protected string _fieldName;
protected byte _maxLength;
public string Value
{
get
{
return _value;
}
protected set
{
if (value == null || string.IsNullOrWhiteSpace(value))
{
throw new ArgumentNullException(_fieldName, _fieldName + " must be supplied.");
}
value = value.Trim();
if (value.Length > _maxLength)
{
throw new ArgumentOutOfRangeException(_fieldName, value, _fieldName + " can't be longer than " + _maxLength.ToString() + " characters.");
}
_value = value;
}
}
}
然后,我可以“使用”所有这些功能的具体类,像这样:
public class FirstName : RequiredStringValueObject
{
private FirstName(string value, string FieldName, byte MaxLength)
{
_fieldName = FieldName;
_maxLength = MaxLength;
Value = value;
}
public static FirstName Create(string value, string FieldName, byte MaxLength)
{
return new FirstName(value, FieldName, MaxLength);
}
protected override IEnumerable<object> GetEqualityCheckAttributes()
{
return new List<object> { Value };
}
}
所有这一切都似乎是一个解决问题的合理方法(对我)。问题是我得到的RequiredStringValueObject声明编译器错误:
类型
string
不能用作泛型类型或方法ValueObject<T>
类型参数T
。没有从string
到ValueObject<string>
的隐式参考转换。
我完全不明白错误消息。我正在尝试做什么?有没有办法做到这一点?还是有另一种方法我可以/应该采取?
我不确定,但为什么你有'where T:ValueObject' –
TryingToImprove
错误是由于如何定义类。你有'公共抽象类ValueObject其中T:ValueObject '。基本上你在说 - 我在声明一个T类的泛型类,这个类只限于这个类的实例。循环定义。 '字符串'不符合那个标准。 –
Sherlock