如何正确设计常用设置

时间:2013-04-11 11:51:36

标签: design-patterns mvvm

此桌面应用程序的业务要求是某些视图上存在常见的过滤器选项。这意味着对于那些包含常见过滤器选项的视图,如果我在一个视图上检查某个选项,则包含它的每个其他视图也需要检查相同的选项(已经显示了许多视图,因此需要更新这些视图)。

CommonSettings { CommonSetting1, CommonSetting2, CommonSetting3, CommonSetting4, CommonSetting5  }
ScreenASettings {ScreenASetting1, ScreenASetting2, CommonSetting2, CommonSetting4 }
ScreenBSettings {ScreenASetting1, CommonSetting1, CommonSetting2, CommonSetting3 }
// and so on

此设置需要保存在文件中以供日后阅读。这个想法是,当屏幕打开时,应用此设置。如果ScreenA和ScreenB都打开了,我在ScreenA上更改CommonSetting2,ScreenB也应该为此设置应用新值,因为它也包含它。

我目前的设计是这样的: - 只存在一个CommonSettings实例 - 我有CommonSettingsViewModel,它包含对CommonSettings实例的引用。 CommonSettingsViewModel处理所有内容:在屏幕上显示选项(向CommonSettingsView公开常用设置,保存常用设置,加载常用设置等) - 每个包含自定义和常用设置的CustomViewModel将(通过DI)引用CustomSetting和CommonSettingViewModel实例。通过这种方式,它可以将创建常用设置的控制权传递给CommonSettingViewModel,并仅处理其自定义设置(加载,保存)

通过这种方法,我分担了自定义和常用设置的责任。我在这里看到的一个缺点是,当我需要查询数据时,我总是需要传递CustomSettings和CommonSettings实例,我需要它们。

您认为这种方法是否正确,或者您认为哪种方法更好?

编辑:这是我用于设置的当前实现

public interface ISettings {
    string ElementPath { get; set; }
    Exception Error { get; }
    object GetValue(string setting);
    bool HasError { get; }
    void Read();
    void Save();
    void SetValue(string setting, object value);
}

// base class for ScreenASettings, CommonSettings, etc
public abstract class SettingsBase : ISettings { ... }

// ancestor class only needs to add settings
public class CommonSettings : BaseSettings {
    private bool _ommonSetting1;
    [Setting]
    public bool CommonSetting1 { .... }
    // CommonSetting2, CommonSetting3, etc
}

1 个答案:

答案 0 :(得分:0)

为什么不定义这样的通用界面:

public interface ISettings
{
    T GetSetting<T>(string key);
    bool TryGetSetting<T>(string key, out T result);
}

然后,您可以接受ISettings作为任何功能的参数,并使用Composite pattern定义可以代表多个其他CompositeSettings个对象的ISettings对象:

public class CompositeSettings : ISettings
{
    private IEnumerable<ISettings> settings;
    public CompositeSettings(params ISettings[] settings)
    {
        this.settings = settings;
    }

    public T GetSetting<T>(string key)
    {
        T result;
        if (TryGetSetting<T>(key, out result))
            return result;
        throw KeyNotFoundException(key);
    }

    public bool TryGetSetting<T>(string key, out T result)
    {
        foreach (var setting in this.settings)
        {
            T innerResult;
            if (setting.TryGetSetting<T>(out innerResult))
            {
                result = innerResult;
                return true;
            }
        }
        return false;
    }
}

(现在我回过头来看看,或许我的命名并不完全有用......可能ISettingsProvider更清楚了)