私は、ここで継承を使用することに苦労している "古い学校"のプログラマーです。私は自分自身がコードを繰り返していることに気がつき、それがにおいを始める。 DRYを守っていなかったので、ここでコードの重複を減らすために少しリファクタリングしようとしています!コンクリートクラスは、抽象クラスから継承する抽象クラスから継承します
私はエンティティで使用されるバリューオブジェクトクラスを作成しようとしています。エンティティは基本インバリアントを適用します。私はそうのような平等とハッシュを扱う一般的な抽象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 };
}
}
このすべてがAのように思えます問題を解決する合理的な方法(私に)。問題は、私はRequiredStringValueObject宣言でコンパイラエラーを取得しています:
タイプ
string
がジェネリック型またはメソッドValueObject<T>
に型パラメータT
として使用することはできません。string
からValueObject<string>
への暗黙の参照変換はありません。
エラーメッセージは正確に分かりません。私がしようとしていることは可能ですか?この仕事をする方法はありますか?または、私は/取るべきである別のアプローチがありますか?
わかりませんが、なぜT:ValueObject ' –
TryingToImprove
エラーがクラスの定義方法に起因するのですか?あなたは 'public abstract class ValueObjectここでT:ValueObject 'を持っています。基本的には、私はTがこのクラスのインスタンスに限定されたジェネリッククラスを宣言しています。円形定義のソート。 'String'はその基準を満たしていません。 –
Sherlock