如何用面向对象设计模式更好地实现基类属性的可扩展性机制



在我的项目中,我有实现自定义属性的类的层次结构。这里更接近于我想要的控制台应用程序版本。

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方法调用,第二个参数设置为true,指示必须推迟属性对象的实例化。

合并后的属性配置的当前状态存储在mergedConfigs Dictionary中。

派生类传递本地属性配置以合并/重写,基类配置调用其构造函数中的MergeWithInheritedConfigsAndCreateInstances方法,第二个参数设置为其默认值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) 合并过程是在每次类被实例化时完成的。

我宁愿只做一次。(放置在静态构造函数中?)

UPD:重写示例代码,更好地展示预期的想法。

我觉得你把事情搞得太复杂了。即使对于复杂的设置,这也应该足够了:

class BaseClass
{
    private readonly Dictionary<string, string> properties = new Dictionary<string, string>();
    protected string this[string key]
    {
        get { string value; return properties.TryGetValue(key, out value) ? value : null; }
        set { if (value == null) properties.Remove(key); else properties[key] = value; }
    }
    public BaseClass()
    {
        this["p1"] = "v1";
        this["p2"] = "v2";
    }
    public override string ToString()
    {
        return GetType().Name + ".Properties: " + string.Join(",", properties.Select(kvp => $"{kvp.Key}:{kvp.Value}"));
    }
}
class DerivedClass : BaseClass
{
    public DerivedClass() : base()
    {
        this["p2"] = "update";
        this["p3"] = "v3";
    }
}

但坦率地说,这更简单、更明显:

class BaseClass
{
    public string P1 {get;set;}
    public string P2 { get; set; }
    public BaseClass()
    {
        P1 = "v1";
        P2 = "v2";
    }
    public override string ToString()
    {
        return GetType().Name + ".Properties: " + string.Join(",", GetType().GetProperties(
            BindingFlags.Public | BindingFlags.Instance).Select(p => $"{p.Name}:{p.GetValue(this)}"));
    }
}
class DerivedClass : BaseClass
{
    public string P3 { get; set; }
    public DerivedClass() : base()
    {
        P2 = "update";
        P3 = "v3";
    }
}

最新更新