C# 重构对Dictionary.Value的安全访问

C# 重构对Dictionary.Value的安全访问,c#,C#,我的目标是重构对Dictionary.Value的安全访问。 我有一个具有动态属性的Json,因此我将其解析为字典~x9000项: var values = JsonConvert.DeserializeObject<List<Dictionary<string, string>>>(json); var values=JsonConvert.DeserializeObject(json); 尝试将其映射到buissness对象,如: foreach (v

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

var values = JsonConvert.DeserializeObject<List<Dictionary<string, string>>>(json);
var values=JsonConvert.DeserializeObject(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);
}
foreach(值中的变量项)
{
var temp=新建BuissnessObject();
字符串ID字符串、名称字符串、类型字符串、地址1字符串、地址2字符串、,
address3String、cityString、postalCodeString、phoneNumberString、,
openAfter8pmString、openOnSundayString、parkingString
//+25行字符串,相当于BuissnessObject属性。
;
如果(item.TryGetValue(“id”,out idString))temp.id=idString;
如果(item.TryGetValue(“name”,out nameString))temp.name=nameString;
如果(item.TryGetValue(“type”,out-typeString))temp.type=typeString;
如果(item.TryGetValue(“address1”,out address1String))临时地址1=address1String;
如果(item.TryGetValue(“address2”,out address2字符串))临时地址2=address2字符串;
如果(item.TryGetValue(“address3”,out address3String))临时地址3=address3String;
如果(项目TryGetValue(“城市”,外城市字符串))温度城市=城市字符串;
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(项TryGetValue(“openOnSunday”,out openOnSundayString))
temp.openOnSunday=bool.Parse(openOnSundayString);
if(项目TryGetValue(“停车”,外停车管柱))
临时停车=布尔解析(停车串);
if(项目TryGetValue(“接收”,输出接收字符串))
临时接收=布尔解析(接收字符串);
// ....
//块动态特性
temp.exceptionalDays=新列表();
foreach(项目中的var k)
{//example:Key=exceptionalDay\u YYYY\u mm\u 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]);
临时例外天数添加(日期);
}
}
}
结果。添加(温度);
}
我正在寻找一种更好的方法来映射这两个实体。或者我反序列化两次:第一次是非动力学性质,忽略动力学性质,然后是动力学性质。 或者我找到了一种缩短映射的方法,如:

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();
}
private static T GetSafe(字典项、字符串键)
{
if(item.TryGetValue(键,输出字符串值))
{
var converter=TypeDescriptor.GetConverter(typeof(T));
if(转换器!=null)
{
return(T)converter.ConvertFromString(值);
}
//无法转换类型为{}的值为{}的键{}-的值
抛出新异常(String.Format(“不可能的de convertir la valeur de{0}-avec la valeur{1}!”,键,值,typeof(T.FullName));
}
其他的
{
//无法卸载键{}的值-此键不存在
抛出新的异常(String.Format(“不可能的de charger la valeur de{0}-Cette clén'existe pas!”,key));
}
抛出新的NotImplementedException();
}
以及一种循环BuissnessObject属性的方法,该属性对于列表中的一个对象是exept


如何处理每个trought BuissnessObject属性名称?

您可以使用反射。给定类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...
    }
}
var businessObject=new businessObject();
var dic=新字典()
{
{“Foo”,“value1”},
{“Bar”,“value2”},
};
//获取属性数组
var properties=GetProperties(businessObject);
foreach(属性中的var p)
{
字符串名称=p.名称;
//跳过你想跳过的
if(myListOfIgnoredProp.Contains(name))
继续;
//喂你想喂的东西
if(dic.TryGetValue(名称,输出var值))
{
if(p.PropertyType==typeof(string))
p、 SetValue(businessObject,value);
else if(p.PropertyType==typeof(bool))
p、 SetValue(businessObject,bool.Parse(value));
//等等。。。
}
}
如果调用
businessObject.ToString()
,您将得到:

Foo:value1,Bar:value2


为什么要将其解析为
字典
,而不仅仅是一个常规的
列表
?事实上,您可以在
//块动态属性
中看到,一些信息是使用名称而不是json中的值发送的。例如,当他们一天不工作时,会发送“NotWorking\u 2018\u 05\u 04”:“True”。因此,我从一个角度使用这个解决方案,真实也有点重要,因为当他们想表明他们将在无人执行的一天工作时,他们会发送“NotWorking\u 2018\u 05\u 04”:“false”。以表明他们会工作。。我无法控制这一切。用一个简单的开关取代我的
GetSafe
真不错!这是我的一票。我会让这个问题持续一周,这样其他人可以在选择获胜者之前尝试回答。但是谢谢你