代码之家  ›  专栏  ›  技术社区  ›  char m

如何用字符串/对象对的集合实现类,以便用泛型方法返回对象?

  •  2
  • char m  · 技术社区  · 15 年前

    DatabaseName=SomeBase
    Classes=11;12;13
    IntValue=3        //this is required!
    DoubleValue=4.0
    

    我是这样想的:

    class ConfigValues
    {
        private static SomeObject _utiObject;
        private static string _cfgFileName = "\\SomeSettings.cfg";
        private static Dictionary<string, Type> _settingNamesAndTypes = 
             new Dictionary<string, Type>();
        private static Dictionary<string, object> _settings = new Dictionary<string, object>();
        private static string _directory = string.Empty;
        const string _impossibleDefaultValue = "987ABC654DEF321GHI";
    
        public static T GetConfigValue<T>(string cfgName)
        {
            object value;
            if (_settings.TryGetValue(cfgName, out value))
                return (T)value;
            else
                return default(T);
        }
    
        public static bool LoadConfig(Dictionary<string, Type> reqSettings, 
              Dictionary<string, Type> optSettings,
              Dictionary<string, object> optDefaultValues, out string errorMsg)
        {
            errorMsg = string.Empty;
    
            try
            {
                _utiObject = new SomeObject(new string[] { "-c", CfgFileNameAndPath });
            }
            catch (Exception e)
            {
                errorMsg = string.Format("Unable to read {0}. Exception: {1}", 
                  CfgFileNameAndPath, e.Message);
                return false;
            }
    
            foreach (KeyValuePair<string, Type> kVPair in reqSettings)
            {
                if (!ReadCheckAndStore(kVPair, null, out errorMsg))
                    return false;
    
                _settingNamesAndTypes.Add(kVPair.Key, kVPair.Value);
    
            }
            foreach (KeyValuePair<string, Type> kVPair in optSettings)
            {
                if (!ReadCheckAndStore(kVPair, optDefaultValues[kVPair.Key], out errorMsg))
                    return false;
    
                _settingNamesAndTypes.Add(kVPair.Key, kVPair.Value);
            }
            return true;
        }
    
        private static bool ReadCheckAndStore(KeyValuePair<string, Type> kVPair, object defaultValue, out string errorMsg)
        {
            errorMsg = string.Empty;
            string usedDefaultValue, value = string.Empty;
    
            /* required setting */
            if (defaultValue == null)
                usedDefaultValue = _impossibleDefaultValue;
            else
                usedDefaultValue = defaultValue.ToString();
    
            //all string parameters below
            _utiObject.GetConfigValue(kVPair.Key, usedDefaultValue, ref value);
            if (_impossibleDefaultValue == value)
            {
                errorMsg = string.Format("Required configuration setting {0} was not" +
                   "found in {1}", kVPair.Key, CfgFileNameAndPath);
                return false;
            }
            Type type = kVPair.Value;
    
            _settings[kVPair.Key] = Convert.ChangeType(value, type);
    
            return true;
        }
    }
    

    附加问题是可选设置的默认值。在单独的字典中将它们传递给LoadConfig并不优雅,但这是另一个问题。。。

    2 回复  |  直到 15 年前
        1
  •  3
  •   Community CDub    8 年前

    我唯一能想到的办法就是 Dictionary<String,Object> Object 到合适的类型。

    基本问题是如何动态指定类型: Dynamically specify the type in C#

    结果发现,C#中的类型转换(实际上是拆箱)开销非常小: C# performance analysis- how to count CPU cycles?


    更新:
    以下是您如何进行铸造:

    Dictionary<String,Object> parameters = new Dictionary<String,Object>();
    
    // cast a string
    parameters.Add("DatabaseName", "SomeBase");
    
    // cast a list
    parameters.Add("Classes", new List<int> { int.Parse("11"), int.Parse("12"), int.Parse("13") });
    
    // cast an integer
    parameters.Add("IntValue", int.Parse("3"));
    
    // cast a double
    parameters.Add("DoubleValue", Double.Parse("4.0"));
    

    int intValue = (int)parameters["IntValue"];
    Double doubleValue = (Double)parameters["DoubleValue"];
    List<int> classes = (List<int>)parameters["Classes"];
    // etc...
    

    正如我之前提到的:在做了性能测试之后,我发现拆箱有疏忽的开销,所以您不应该看到任何明显的性能问题。


    更新2.0:

    我猜您希望在将类型添加到 _settings 字典。如果你的字典的值是 对象 :

    Type t = typeof(double);
    Object val = Convert.ChangeType("2.0", t);
    // you still need to unbox the value to use it
    double actual = (double)val;
    

    _settings[kVPair.Key] = Convert.ChangeType(value, type);
    

    当您要使用它时,您只需要用正确的类型取消对值的装箱。

        2
  •  0
  •   Tim Jarvis    15 年前

    你可以有三种方法

    public string GetStringConfig(string key){}
    public List<int> GetListConfig(string key){}
    public int GetIntegerConfig(string key){}
    

    当然,这假设您知道键应该返回的对象类型