Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何将JSON动态转换为正确的DTO类?_C#_Casting_Mono_Type Conversion_Dynamic Data - Fatal编程技术网

C# 如何将JSON动态转换为正确的DTO类?

C# 如何将JSON动态转换为正确的DTO类?,c#,casting,mono,type-conversion,dynamic-data,C#,Casting,Mono,Type Conversion,Dynamic Data,我有JSON数据,我想转换成正确的类型,然后处理它。我正在使用MONO和NewtonSoft的JSON库。也就是说,JSON和object必须匹配属性1:1才能转换为正确的DTO。DTO始终具有独特的属性 Activator.CreateInstance()和Convert.ChangeType()似乎都未编译 DTO: 服务器: using System; using System.Collections.Generic; using System.Linq; using System.Thr

我有JSON数据,我想转换成正确的类型,然后处理它。我正在使用MONO和NewtonSoft的JSON库。也就是说,JSON和object必须匹配属性1:1才能转换为正确的DTO。DTO始终具有独特的属性

Activator.CreateInstance()和Convert.ChangeType()似乎都未编译

DTO:

服务器:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Newtonsoft.Json;

class Server
{
    protected static List<JSONDTO> DTOList; 

    static void Main()
    {
        DTOList = new List<JSONDTO>();

        DTOList.Add(new JSONProfileDTO());
        DTOList.Add(new JSONCommandDTO());
        DTOList.Add(new JSONMessageDTO());

        // ...

    }

    protected static void OnMessage (string message)
    {
        dynamic rawObject;

        try
        {
            // Or try to convert to right DTO here somehow?
            rawObject = JsonConvert.DeserializeObject<dynamic>(message);
        } catch (JsonReaderException ex) {
            // Invalid JSON
            return;
        }

        int dtoCount = DTOList.ToArray().Length;
        int errCount = 0;

        JSONDTO DTOObject;

        foreach (var dto in DTOList.ToList()) {
            try {
                // Doesn't compile:

                // DTOObject = Activator.CreateInstance(dto.GetType(), rawObject);
                // DTOObject = Convert.ChangeType(rawObject, dto.GetType());
                break; // Match found!
            } catch (Exception ex) {
                // Didn't match
                errCount++;
            }
        }

        if (errCount == dtoCount) {
            // Right DTO was not found
            return;
        }


        if (DTOObject is JSONProfileDTO) {
            AssignProfile((JSONProfileDTO) DTOObject);
        }
        else if (DTOObject is JSONCommandDTO)
        {
            RunCommand((JSONCommandDTO) DTOObject);
        }
        // etc ..

    }

    protected static void RunCommand (JSONCommandDTO command)
    {
        string cmd = command.cmd;

        Console.WriteLine("command == " + cmd);
    }

    protected static void AssignProfile(JSONProfileDTO profile)
    {
        Console.WriteLine("got profile!");
    }

}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统线程;
使用Newtonsoft.Json;
类服务器
{
受保护的静态列表数据列表;
静态void Main()
{
DTOList=新列表();
Add(新的JSONProfileDTO());
Add(新的JSONCommandDTO());
Add(新的JSONMessageDTO());
// ...
}
受保护的静态无效消息(字符串消息)
{
动态对象;
尝试
{
//或者试着在这里转换成正确的DTO?
rawObject=JsonConvert.DeserializeObject(消息);
}捕获(JsonReaderException ex){
//无效的JSON
返回;
}
int dtoCount=DTOList.ToArray().Length;
int errCount=0;
JSONDTO对象;
foreach(DTOList.ToList()中的变量dto){
试一试{
//不编译:
//DTOObject=Activator.CreateInstance(dto.GetType(),rawObject);
//DTOObject=Convert.ChangeType(rawObject,dto.GetType());
break;//找到匹配项!
}捕获(例外情况除外){
//不匹配
errCount++;
}
}
if(errCount==dtoCount){
//找不到正确的DTO
返回;
}
if(DTOObject是JSONProfileDTO){
AssignProfile((JSONProfileDTO)DTOObject);
}
else if(DTOObject是JSONCommandDTO)
{
RunCommand((JSONCommandDTO)DTOObject);
}
//等等。。
}
受保护的静态void RunCommand(JSONCommandDTO命令)
{
字符串cmd=command.cmd;
Console.WriteLine(“command==”+cmd);
}
受保护的静态配置文件(JSONProfileDTO配置文件)
{
控制台。WriteLine(“获得配置文件!”);
}
}

}

我假设您自己没有从DTO类创建序列化数据,因为在这种情况下,您可以让它在输出中包含类型信息。有了这些信息,反序列化程序将能够自动重新创建正确的实例

由于这很可能不是您的情况,您需要解决以下问题:

  • 解析JSON并创建具有相应属性的对象
  • 确定哪个DTO实例与给定数据匹配
  • 创建DTO实例并使用在步骤1中创建的对象填充它
  • 我假设您已经或者可以找到一个JSON反序列化程序来处理第一步

    您可能有一种更简单的方法来执行步骤2,但简单的方法只是比较JSON数据中可用的属性名称,并找到具有精确匹配的DTO。这可能看起来像这样(用于辅助反射位):

    步骤3的代码可能如下所示:

    // match is the DTO type to create
    var dto = match.TryCreateInstance( json );
    
    TryCreateInstance是另一个Fasterflect助手-它将自动找到一个构造函数来调用和复制任何剩余的匹配属性


    我希望这为您指明了正确的方向。

    我成功了。我必须添加带有MissingMemberHandling.Error的JSONSerializerSetting,以便在JSON不适合对象时引发异常。我还缺少Microsoft.CSharp参考

    class Server
    {
        protected static List<Type> DTOList = new List<Type>(); 
    
        static void Main()
        {
            DTOList.Add(typeof(JSONProfileDTO));
            DTOList.Add(typeof(JSONCommandDTO));
            DTOList.Add(typeof(JSONMessageDTO));
        }
    
        protected static void OnMessage (string rawString)
        {
            dynamic jsonObject = null;
            int DTOCount = DTOList.Count;
            int errors = 0;
    
            var settings = new JsonSerializerSettings ();
    
            // This was important
            // Now exception is thrown when creating invalid instance in the loop
            settings.MissingMemberHandling = MissingMemberHandling.Error;
    
            foreach (Type DTOType in DTOList) {
                try {
                    jsonObject = JsonConvert.DeserializeObject (rawString, DTOType, settings);
                    break;
                } catch (Exception ex) {
                    errors++;
                }
            }
    
            if (null == jsonObject) {
                return;
            }
    
            if (errors == DTOCount) {
                return;
            }
    
            if (jsonObject is JSONProfileDTO) {
                AssignProfile((JSONProfileDTO) jsonObject);
            }
            else if (jsonObject is JSONCommandDTO)
            {
                RunCommand((JSONCommandDTO) jsonObject);
            }
    
        }
    
    }
    
    类服务器
    {
    受保护的静态列表DTOList=新列表();
    静态void Main()
    {
    添加(typeof(JSONProfileDTO));
    添加(typeof(JSONCommandDTO));
    Add(typeof(JSONMessageDTO));
    }
    受保护的静态void OnMessage(字符串rawString)
    {
    动态jsonObject=null;
    int DTOCount=DTOList.Count;
    整数误差=0;
    var settings=newjsonserializersettings();
    //这很重要
    //现在,在循环中创建无效实例时引发异常
    settings.MissingMemberHandling=MissingMemberHandling.Error;
    foreach(在DTOList中键入DTOType){
    试一试{
    jsonObject=JsonConvert.DeserializeObject(原始字符串、数据类型、设置);
    打破
    }捕获(例外情况除外){
    错误++;
    }
    }
    if(null==jsonObject){
    返回;
    }
    如果(错误==DTOCount){
    返回;
    }
    if(jsonObject是JSONProfileDTO){
    AssignProfile((JSONProfileDTO)jsonObject);
    }
    else if(jsonObject是JSONCOMMANDTO)
    {
    RunCommand((JSONCommandDTO)jsonObject);
    }
    }
    }
    
    // match is the DTO type to create
    var dto = match.TryCreateInstance( json );
    
    class Server
    {
        protected static List<Type> DTOList = new List<Type>(); 
    
        static void Main()
        {
            DTOList.Add(typeof(JSONProfileDTO));
            DTOList.Add(typeof(JSONCommandDTO));
            DTOList.Add(typeof(JSONMessageDTO));
        }
    
        protected static void OnMessage (string rawString)
        {
            dynamic jsonObject = null;
            int DTOCount = DTOList.Count;
            int errors = 0;
    
            var settings = new JsonSerializerSettings ();
    
            // This was important
            // Now exception is thrown when creating invalid instance in the loop
            settings.MissingMemberHandling = MissingMemberHandling.Error;
    
            foreach (Type DTOType in DTOList) {
                try {
                    jsonObject = JsonConvert.DeserializeObject (rawString, DTOType, settings);
                    break;
                } catch (Exception ex) {
                    errors++;
                }
            }
    
            if (null == jsonObject) {
                return;
            }
    
            if (errors == DTOCount) {
                return;
            }
    
            if (jsonObject is JSONProfileDTO) {
                AssignProfile((JSONProfileDTO) jsonObject);
            }
            else if (jsonObject is JSONCommandDTO)
            {
                RunCommand((JSONCommandDTO) jsonObject);
            }
    
        }
    
    }