重构对Dictionary.Value的安全访问

时间:2018-05-04 11:32:39

标签: c#

我的目标是重构对Dictionary.Value的安全访问 我有一个具有动态属性的Json,因此我将其解析为Dictionary<string, string> ~x9000项:

var values = JsonConvert.DeserializeObject<List<Dictionary<string, string>>>(json);

尝试将此映射到buissness对象,如:

foreach (var item in values)
{

    var temp = new BuissnessObject();


    string idString, nameString, typeString, address1String, address2String,
        address3String, cityString, postalCodeString, phoneNumberString,
        openAfter8pmString, openOnSundayString, parkingString
        // + 25 lines of string equivalent of BuissnessObject properties.
        ;

    if (item.TryGetValue("id", out idString)) temp.id = idString;
    if (item.TryGetValue("name", out nameString)) temp.name = nameString;
    if (item.TryGetValue("type", out typeString)) temp.type = typeString;

    if (item.TryGetValue("address1", out address1String)) temp.address1 = address1String;
    if (item.TryGetValue("address2", out address2String)) temp.address2 = address2String;
    if (item.TryGetValue("address3", out address3String)) temp.address3 = address3String;
    if (item.TryGetValue("city", out cityString)) temp.city = cityString;
    if (item.TryGetValue("postalCode", out postalCodeString)) temp.postalCode = postalCodeString;
    if (item.TryGetValue("phoneNumber", out phoneNumberString)) temp.phoneNumber = phoneNumberString;


    if (item.TryGetValue("openAfter8pm", out openAfter8pmString))
        temp.openAfter8pm = bool.Parse(openAfter8pmString);

    if (item.TryGetValue("openOnSunday", out openOnSundayString))
        temp.openOnSunday = bool.Parse(openOnSundayString);

    if (item.TryGetValue("parking", out parkingString))
        temp.parking = bool.Parse(parkingString);

    if (item.TryGetValue("reception", out receptionString))
        temp.reception = bool.Parse(receptionString);
    // ....


    // Block Dynamic properties
    temp.exceptionalDays = new List<DateTime>();

    foreach (var k in item)
    {   // Exemple: Key = exceptionalDay_YYYY_mm_dd ;  Value = True
        if (k.Key.StartsWith("exceptionalDay") && bool.Parse(k.Value))
        {
            var dateRaw = k.Key.Split('_').Skip(1).ToArray();
            if (dateRaw.Count() == 3)
            {
                var date = new DateTime(int.Parse(dateRaw[0]), int.Parse(dateRaw[1]), int.Parse(dateRaw[2]));
                temp.exceptionalDays.Add(date);
            }
        }
    }


    result.Add(temp);
}

我&#39;我正在寻找一种更好的方法来映射这两个实体。要么我反序列化两次:第一次是非动态属性忽略动态属性,然后只是动态。 或者我找到了缩短映射的方法,如:

private static T GetSafe<T>(Dictionary<string, string> item, string key)
{
    if (item.TryGetValue(key, out string value))
    {
        var converter = TypeDescriptor.GetConverter(typeof(T));
        if (converter != null)
        {
            return (T)converter.ConvertFromString(value);
        }
        // Impossible to convert value of key {} - with value ={} for  type={}
        throw new Exception(String.Format("Impossible de convertir la valeur de {0} - avec la valeur {1} !", key,value, typeof(T).FullName));
    }
    else
    {
        //Impossible de load the value of key {} - this key doesn't exist
        throw new Exception(String.Format("Impossible de charger la valeur de {0} - Cette clé n'existe pas !", key));
    }
    throw new NotImplementedException();
}

循环BuissnessObject属性的方法是对List中的那个进行循环。

如何预测BuissnessObject属性名称?

1 个答案:

答案 0 :(得分:2)

你可以使用反思。鉴于BuissnessObject类:

class BuissnessObject
{
    public String Foo { get; set; }
    public String Bar { get; set; }

    public override string ToString()
    {
        return $"Foo : {Foo}, Bar : {Bar}";
    }
}

这个小助手:

private static PropertyInfo[] GetProperties(object obj)
{
    return obj.GetType().GetProperties();
}

您可以使用以下代码:

var businessObject = new BuissnessObject();

var dic = new Dictionary<string, string>()
{
    {"Foo", "value1" },
    {"Bar", "value2" },

};
// Get property array
var properties = GetProperties(businessObject);

foreach (var p in properties)
{
    string name = p.Name;

    // Skip what you want to skip
    if(myListOfIgnoredProp.Contains(name))
        continue;

    // Feed what you want to feed
    if (dic.TryGetValue(name, out var value))
    {
        if(p.PropertyType == typeof(string))
            p.SetValue(businessObject, value);
        else if (p.PropertyType == typeof(bool))
            p.SetValue(businessObject, bool.Parse(value));
        //And so on...
    }
}
< p>如果你致电businessObject.ToString(),你将获得:

  

Foo:value1,Bar:value2