我是一個「老派」程序員,在這裏正在努力繼承我的優勢。我發現自己重複了代碼,並開始聞起來。我沒有堅持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