前回までのおさらいと改良
前回では静的メソッドとしての”プロパティとしてのクラス”のgetterとsetterを定義した。
これを汎化拡張メソッドとして書き直した。
namespace ClassAsProperty
{
public static class ClassAsPropertyMethodBase
{
public static T? GetmethodT<T, T2>(this T2 TargetPoperty) where T : struct where T2 : ICompornentClass<T>
{
return TargetPoperty?.Value;
}
public static void SetmethodT<T, T2>(this T2 TargetProperty, T value) where T : struct where T2 : ICompornentClass<T>, new()
{
if (TargetProperty is null)
{ TargetProperty = new T2(); }
TargetProperty.Value = value;
}
}
}
ICompornentClass<T>の中身はこちら
public interface ICompornentClass<T> where T : struct
{
public int ID { get; set; }
public T Value { get; set; }
}
まず準備はここまで、何をしたかというとICompornetClassを継承したクラスは
GetMethodTとSetMethodTをジェネリックメソッドとして呼び出せるように定義しました。
応用:期限切れ管理クラス
まずはOne to Oneの関係性を念頭に置いた応用として期限日の定義を行います。
Compornentクラスのインターフェイス、Compositeクラスのインターフェイスと実装を以下に示します。
public class ExpireDayCompornent<T>: ICompornentClass<DateTime> where T : AbstractExpiredayBaseClass<T>
{
public ExpireDayCompornent() { Value = System.DateTime.Now; }
public ExpireDayCompornent(DateTime value) { Value = value; }
public int ID { get; set; }
public DateTime Value { get; set; }
public T ExpiredComposteNavigation { get; set; }
}
上記のジェネリックインターフェイスを用いてCompornentクラスを実装する。
public interface IExpireDayConpositeClass
{
public int ID { get; set; }
public DateTime CreatedDateTime { get; set; }
public DateTime? ExpiredDateTime();
public void ExpiredDateTime(DateTime value);
}
Compositeクラスのインターフェイスを実装しておく。
単に自動実装実装プロパティにしたかったがnullableが問題になったのでオーバーロードで対応した。
これは後でFluent APIでの実装でかかわってくる。
public abstract class AbstractExpiredayBaseClass<T>: IExpireDayConpositeClass where T : AbstractExpiredayBaseClass<T>
{
public int ID {get; set;}
public DateTime CreatedDateTime { get; set; }
private ExpireDayCompornent<AbstractExpiredayBaseClass<T>> ExpireDayCompornent { get; set; }
public DateTime? ExpiredDateTime() => ExpireDayCompornent.GetmethodT<DateTime, ExpireDayCompornent<AbstractExpiredayBaseClass<T>>>();
public void ExpiredDateTime(DateTime value) => ExpireDayCompornent.SetmethodT<DateTime, ExpireDayCompornent<AbstractExpiredayBaseClass<T>>>(value);
}
これがその実装である。このアブストラクトクラスが継承され実装された後に
自己参照ジェネリックで定義可能である。
独自のFluent API実装に向けて
ところで、このクラスのモデルビルダーを実装すればうまく行くけど
何を返せばいいのか迷うと思うが多分これだ
https://docs.microsoft.com/en-us/dotnet/api/system.data.entity.infrastructure.dbentityentry-1?view=entity-framework-6.2.0
public System.Data.Entity.Infrastructure.DbEntityEntry<TEntity> Entry<TEntity> (TEntity entity) where TEntity : class;
このDbEntityEntryを返すジェネリック拡張メソッドにしておけば一発でコンテキスト定義可能なはず。