我的通用解耦非常丑陋

本文关键字:非常 解耦 我的 | 更新日期: 2023-09-27 17:51:11

我正在创建一个可以处理设置和加载/保存设置的dll。

我有一个设置类的属性,如string Path, DateTime LastOpened等。设置可以是任何东西,唯一的要求是它有一种默认值的方式。

有一个不同的类负责加载/保存设置。该类可以接受任何设置类并(反)序列化为任何文件格式。例如,它可以从XML文件中加载某种类型的设置,或者从JSON文件中加载相同类型的设置。

我的设计最终有点奇怪。

我为所有的设置类定义了一个接口,这样我就知道DefaultSettings()是可用的。

interface ISettings<T>
{
    T DefaultSettings();
}

我的设置类看起来像:

public class MySettings : ISettings<MySettings>
{
    public DateTime LastOpened;
    public string Path;
    public MySettings DefaultSettings()
    {
        LastOpened = DateTime.Now;
        Path = @"c:'";
    }
}

实现类告诉它自己的接口看起来已经很奇怪了。

加载/保存类实现了这个接口:

interface ISettingsFile<T>
{
    T Load(string file);
    void Save();
}

假设我想从XmlSettingsFile<MySettings>加载MySettings。我必须写一些难看的东西,比如

MySettings mySettings = new MySettings();
XmlSettingsFile<MySettings> file = new XmlSettingsFile<MySettings>();
try {
    mySettings = file.Load();
} catch (FileNotFoundException)
{
    mySettings = mySettings.DefaultSettings();
}

这简直太奇怪和丑陋了。一定有更好的办法。

你有什么好主意吗?

我的通用解耦非常丑陋

我不认为你的方法丑陋。使用中间字符串表示或类似的东西当然更好。

所以我会说你的方法很好,保持原样

这样如何:

interface ISettings 
{ 
    public string GetSetting(string settingName, string defaultValue);
} 

所以不要尝试将设置表示为属性,而是使用命名值。这样就更容易考虑加载/保存设置,也更容易通过方法重载将职责传递给不同的类。如果你喜欢的话,你可以用动态模式来完成这些,但我个人喜欢这种模式,它让事情变得简单。

您也可以添加泛型,但您通常会发现这样的几个方法就足够了:

    public bool GetSettingBool(string settingName, bool defaultValue);

这将抽象出您的阅读器实现(xml, json,等等)…

 public interface IConfigurationReader
{
    T Read<T>(string configKey);
}
public class Configuration
{
    private readonly IConfigurationReader _reader;
    public Configuration(IConfigurationReader reader)
    {
        _reader = reader;
    }
    public string Path
    {
        get
        {
            var path = _reader.Read<string>("Path");
            return path;
        }
    }
}
public class ApplicationConfigFileReader : IConfigurationReader
{
    public T Read<T>(string configKey)
    {
        var settingValue = System.Configuration.ConfigurationManager.AppSettings[configKey];
        return (T)Convert.ChangeType(settingValue, typeof(T));
    }
}
//sample usage
class Program
{
    static void Main(string[] args)
    {
        IConfigurationReader reader = new ApplicationConfigFileReader();
        var config = new Configuration(reader);
        Console.WriteLine(config.Path);
        Console.ReadKey();
    }
}

My Reader实现只是作为框架类型的适配器,用于读取应用程序配置文件。

如果你有很多设置,按类别/区域将它们分组到单独的界面中是有益的。