私のプロジェクトでは、カスタムプロパティを実装するクラスの階層を持っています。ここで私はコンソールアプリケーション用のバージョンに近いものです。OOPデザインパターンで基本クラスのプロパティ拡張メカニズムをよりよく実装する方法
class Property
{
string key;
object value;
public Property(string key, object value)
{
this.key = key;
this.value = value;
}
public override string ToString()
{
return "(key=" + key + ": value=" + value + ")";
}
}
public struct PropertyConfig
{
public string key;
public object defaultValue;
}
abstract class BaseClass
{
Dictionary<string, Property> properties = new Dictionary<string, Property>();
Dictionary<string, PropertyConfig> mergedConfigs = new Dictionary<string, PropertyConfig>();
public BaseClass()
{
MergeWithInheritedConfigsAndCreateInstances(
new PropertyConfig[]
{
new PropertyConfig() { key = "p1", defaultValue = "v1" },
new PropertyConfig() { key = "p2", defaultValue = "v2" }
},
true);
}
protected void MergeWithInheritedConfigsAndCreateInstances(PropertyConfig[] configs = null, bool IsBaseClass = false)
{
configs = configs ?? new PropertyConfig[] { };
foreach (PropertyConfig config in configs)
{
mergedConfigs[config.key] = config;
}
if (!IsBaseClass)
{
CreatePropertyInstancesAfterMerge();
}
}
private void CreatePropertyInstancesAfterMerge()
{
foreach (KeyValuePair<string, PropertyConfig> kvp in mergedConfigs)
{
PropertyConfig config = kvp.Value;
properties.Add(config.key, new Property(config.key, config.defaultValue));
}
}
public override string ToString()
{
return GetType().Name + ".Properties: " + string.Join(",", properties.Select(kvp => kvp.Value.ToString()).ToArray());
}
}
class DerivedClassA : BaseClass
{
public DerivedClassA(): base()
{
MergeWithInheritedConfigsAndCreateInstances();
}
}
class DerivedClassB : BaseClass
{
public DerivedClassB() : base()
{
MergeWithInheritedConfigsAndCreateInstances(new PropertyConfig[]
{
new PropertyConfig() { key = "p2", defaultValue = true },
new PropertyConfig() { key = "p3", defaultValue = "v3" }
});
}
}
class DerivedClassC : BaseClass
{
public DerivedClassC() : base()
{
MergeWithInheritedConfigsAndCreateInstances(new PropertyConfig[]
{
new PropertyConfig() { key = "p2", defaultValue = false },
new PropertyConfig() { key = "p4", defaultValue = "v4" }
});
}
}
class Program
{
static void Main(string[] args)
{
DerivedClassA derivedA = new DerivedClassA();
DerivedClassB derivedB = new DerivedClassB();
DerivedClassC derivedC = new DerivedClassC();
Console.WriteLine(derivedA.ToString());
Console.WriteLine(derivedB.ToString());
Console.WriteLine(derivedC.ToString());
Console.ReadLine();
}
}
基本抽象クラスは、派生クラスで継承されることを意図したプロパティオブジェクトの構成を定義します。
コンストラクタのコンフィグレーションでは、配列オブジェクトはMergeWithInheritedConfigsAndCreateInstances
メソッドコールに渡され、2番目のパラメータはtrue
に設定され、プロパティオブジェクトのインスタンス化を延期する必要があることを示します。
マージされたプロパティ設定の現在の状態は、mergedConfigs
Dictionary
に格納されます。
派生クラスは、コンストラクタでMergeWithInheritedConfigsAndCreateInstances
メソッドを呼び出す基本クラス構成とマージ/オーバーライドするローカルプロパティ設定を渡し、2番目のパラメータをデフォルト値のfalse
に設定して、今すぐマージ後にプロパティインスタンスを作成する必要があることを示します。
結果は次のとおりです。
DerivedClassA.Properties: (key=p1: value=v1),(key=p2: value=v2)
DerivedClassB.Properties: (key=p1: value=v1),(key=p2: value=True),(key=p3: value=v3)
DerivedClassC.Properties: (key=p1: value=v1),(key=p2: value=False),(key=p4: value=v4)
そして、それは私が必要なものですが、私は好きではない、このソリューションのいくつかの欠点があります。
1)各コンストラクタでMergeWithInheritedConfigsAndCreateInstances
を呼び出す必要があります。 2番目のパラメータは、抽象クラスコンストラクタで提供する必要があります。
すべてのマージ/インスタンス化メカニズムが実装され、基本クラスで呼び出されたソリューションが必要です。また、派生クラス固有のプロパティ設定をメソッドパラメータとしてではなく、メンバーフィールド/プロパティとして(静的なのかもしれません)定義することができます。
2)マージ処理は、クラスがインスタンス化されるたびに実行されます。
私はそれを1回だけ行うことを好むでしょう。 (静的コンストラクタに配置しますか?)
UPD:意図した考え方をよりよく示す書き換えられたサンプルコードです。
FYI:これはXAML/WPFは、依存関係プロパティでボンネットの下にどのように動作するか..です –
私のコードでは、wpf構造に依存することはできません。同様の要件があるように見えますが、wpf依存関係プロパティシステムの内部実装は、そのドメイン固有のものであり、実装の詳細をそのままここで再利用することはできません。 –
具体的なクラスを再利用することではなく、その背後にあるアイデア.../ –