减少根据数据类型获取设置的方法数量

Decrease amount of methods to get settings based on data type

所以我有一个 table 可以让我的移动应用程序的设置在开发接近尾声时保持不变,我忍不住认为这是一种更简洁的方法。

我将如何进行一次调用来解释返回的不同数据类型,而不是进行三个单独的调用。

我在 Web api 项目中使用 ef core 6 和 c# 7。

public class SettingsService
{

    TheAppDBContext db;
    public SettingsService(TheAppDBContext dBContext)
    {
        db = dBContext;
    }

    public List<Settings> GetALLSettings()
    {
      return db.Settings.Where(w => w.IsActive == true && 
      w.IsDeleted == false).ToList();
    }
    public bool? GetBoolSettingValueByKey(string Key)
    {

        return db.Settings.Where(w => w.IsActive == true && w.IsDeleted == false 
        && w.Key.ToLower() == Key.ToLower()).First().BoolValue;
    }
    public string? GetStringSettingValueByKey(string Key)
    {

        return db.Settings.Where(w => w.IsActive == true && w.IsDeleted == false && 
        w.Key.ToLower() == Key.ToLower()).First().StringValue;
    }
    public int? GetIntSettingValueByKey(string Key)
    {

        return db.Settings.Where(w => w.IsActive == true && w.IsDeleted == false && 
        w.Key.ToLower() == Key.ToLower()).First().IntValue;
    }
}

我的 Table 设置如下,将来可能会在设置 table 中存储日期和其他数据类型。

如果您愿意失去一些类型安全性,您可以使用使您的方法成为通用方法并分析它的通用类型参数:

public T GetSettingValueByKey<T>(string key)
{
    var setting = db.Settings
        .Where(w => w.IsActive == true && w.IsDeleted == false && w.Key.ToLower() == Key.ToLower())
        .First();

    var type = typeof(T);
    if (type == typeof(bool))
    {
        return (T)(object)setting.BoolValue;
    }
    if (type == typeof(string))
    {
        return (T)(object)setting.StringValue;
    }
    if (type == typeof(int))
    {
        return (T)(object)setting.IntValue;
    }
    ...
    throw new InvalidOperationException();
}

这里的问题是没有人限制用户使用不受支持的类型调用 GetSettingValueByKey 并且编译器无法强制执行(除非您想深入编写自定义代码分析器)。

为了在没有自定义分析器的情况下保持编译时安全,您可以尝试引入类型层次结构来表示可能的设置类型:

public interface ISettingValue{}
public interface ISettingValue<T> : ISettingValue
{
    T Value { get; set; }
}

public struct IntSettingValue : ISettingValue<int?>
{
    public int? Value { get; set; }
}
public struct BoolSettingValue : ISettingValue<bool?>
{
    public bool? Value { get; set; }
}   
...
public T GetSettingValueByKey<T>(string key) where T : ISettingValue
{
    var setting = db.Settings
        .Where(w => w.IsActive == true && w.IsDeleted == false && w.Key.ToLower() == Key.ToLower())
        .First();

    var type = typeof(T);
    if (type == typeof(BoolSettingValue))
    {
        return (T)(object)new BoolSettingValue
        {
            Value = setting.BoolValue
        };
    }

    if (type == typeof(int))
    {
        return (T)(object)new IntSettingValue
        {
            Value = setting.IntValue
        };
    }
    ...
    throw new InvalidOperationException(); // write unit test with reflection to validate that this never happens
}

和用法:

SettingsService service = ...;
int? val = service.GetSettingValueByKey<IntSettingValue>("").Value;