2015-01-24 4 views
0

두 번째 응용 프로그램은 redis 서버의 도움을 받아 서로 통신합니다. 첫 번째 응용 프로그램에서는 serialize 할 수 있으며 다음과 같은 형식의 객체를 직렬화하고 객체화합니다.JSON 문자열의 비 직렬화 중에 이름 공간이 변경됨

{ 
"$type": "System.Collections.Generic.Dictionary`2[[System.Int32, mscorlib], [OPCMessagingService.Resource, OPCMessagingService]], mscorlib", 
"71": { 
"$type": "OPCMessagingService.Resource, OPCMessagingService", 
"SiteID": 2, 
"ResourceID": 71, 
"ProcessOrder": "001000380873", 
"CurrentStatus": 0, 
"CycleTime": 55, 
"DeviceList": [ 
    { 
    "$type": "OPCMessagingService.StackLight, OPCMessagingService", 
    "ResourceId": 71, 
    "DeviceIp": "10.142.117.7", 
    "ComPort": "COM14" 
    }, 
    { 
    "$type": "OPCMessagingService.LED, OPCMessagingService", 
    "ResourceId": 71, 
    "DeviceIp": "10.142.117.3", 
    "ComPort": "COM10", 
    "IsMessageDelivered": false, 
    "RetryCount": 3, 
    "IsRetryRequired": true, 
    "_messageHeader": ":*HF601011471", 
    "_messageText": "DISPOMELT 5245 BULK - 0020 -投矿物油,树脂,液体树脂和橡胶", 
    "_delayedMessageText": "", 
    "_counter": 0 
    } 
], 
"UpdateDate": 20150120, 
"UpdateTime": 231506, 
"CurrentDate": 20150124, 
"CurrentTime": 151513, 
"CurrentMessage": "DISPOMELT 5245 BULK - 0020 -投矿物油,树脂,液体树脂和橡胶" 
    }, 
    "72": { 
"$type": "OPCMessagingService.Resource, OPCMessagingService", 
"SiteID": 2, 
"ResourceID": 72, 
"ProcessOrder": "001000380874", 
"CurrentStatus": 0, 
"CycleTime": 60, 
"DeviceList": [ 
    { 
    "$type": "OPCMessagingService.LED, OPCMessagingService", 
    "ResourceId": 72, 
    "DeviceIp": "10.142.117.98", 
    "ComPort": "COM100", 
    "IsMessageDelivered": false, 
    "RetryCount": 3, 
    "IsRetryRequired": true, 
    "_messageHeader": ":*HF601011471", 
    "_messageText": "DISPOMELT 5245 BULK - 0050 -熔树脂", 
    "_delayedMessageText": "", 
    "_counter": 0 
    }, 
    { 
    "$type": "OPCMessagingService.LED, OPCMessagingService", 
    "ResourceId": 72, 
    "DeviceIp": "10.142.117.4", 
    "ComPort": "COM11", 
    "IsMessageDelivered": false, 
    "RetryCount": 3, 
    "IsRetryRequired": true, 
    "_messageHeader": ":*HF601011471", 
    "_messageText": "DISPOMELT 5245 BULK - 0050 -熔树脂", 
    "_delayedMessageText": "", 
    "_counter": 0 
    }, 
    { 
    "$type": "OPCMessagingService.StackLight, OPCMessagingService", 
    "ResourceId": 72, 
    "DeviceIp": "10.142.117.8", 
    "ComPort": "COM15" 
    }, 
    { 
    "$type": "OPCMessagingService.StackLight, OPCMessagingService", 
    "ResourceId": 72, 
    "DeviceIp": "10.142.117.97", 
    "ComPort": "COM101" 
    } 
], 
"UpdateDate": 20150120, 
"UpdateTime": 231534, 
"CurrentDate": 20150124, 
"CurrentTime": 151513, 
"CurrentMessage": "DISPOMELT 5245 BULK - 0050 -熔树脂" 
    }, 
    "73": { 
"$type": "OPCMessagingService.Resource, OPCMessagingService", 
"SiteID": 2, 
"ResourceID": 73, 
"ProcessOrder": "001000375454", 
"CurrentStatus": 0, 
"CycleTime": 60, 
"DeviceList": [ 
    { 
    "$type": "OPCMessagingService.LED, OPCMessagingService", 
    "ResourceId": 73, 
    "DeviceIp": "10.142.117.5", 
    "ComPort": "COM12", 
    "IsMessageDelivered": false, 
    "RetryCount": 3, 
    "IsRetryRequired": true, 
    "_messageHeader": ":*HF601011471", 
    "_messageText": "XHC 9228 BULK - 0050 -熔树脂", 
    "_delayedMessageText": "", 
    "_counter": 0 
    }, 
    { 
    "$type": "OPCMessagingService.StackLight, OPCMessagingService", 
    "ResourceId": 73, 
    "DeviceIp": "10.142.117.9", 
    "ComPort": "COM16" 
    } 
], 
"UpdateDate": 20150120, 
"UpdateTime": 223043, 
"CurrentDate": 20150124, 
"CurrentTime": 151513, 
"CurrentMessage": "XHC 9228 BULK - 0050 -熔树脂" 
    }, 
    "74": { 
"$type": "OPCMessagingService.Resource, OPCMessagingService", 
"SiteID": 2, 
"ResourceID": 74, 
"ProcessOrder": "001000375455", 
"CurrentStatus": 0, 
"CycleTime": 40, 
"DeviceList": [ 
    { 
    "$type": "OPCMessagingService.LED, OPCMessagingService", 
    "ResourceId": 74, 
    "DeviceIp": "10.142.117.2", 
    "ComPort": "COM9", 
    "IsMessageDelivered": false, 
    "RetryCount": 3, 
    "IsRetryRequired": true, 
    "_messageHeader": ":*HF601011471", 
    "_messageText": "XHC 9228 BULK - 0040 -投树脂和剩料:", 
    "_delayedMessageText": "", 
    "_counter": 0 
    }, 
    { 
    "$type": "OPCMessagingService.StackLight, OPCMessagingService", 
    "ResourceId": 74, 
    "DeviceIp": "10.142.117.1", 
    "ComPort": "COM5" 
    } 
], 
"UpdateDate": 20150120, 
"UpdateTime": 224143, 
"CurrentDate": 20150124, 
"CurrentTime": 151513, 
"CurrentMessage": "XHC 9228 BULK - 0040 -投树脂和剩料:" 
    }, 
    "75": { 
"$type": "OPCMessagingService.Resource, OPCMessagingService", 
"SiteID": 2, 
"ResourceID": 75, 
"ProcessOrder": "001000375456", 
"CurrentStatus": 0, 
"CycleTime": 50, 
"DeviceList": [ 
    { 
    "$type": "OPCMessagingService.StackLight, OPCMessagingService", 
    "ResourceId": 75, 
    "DeviceIp": "10.142.117.10", 
    "ComPort": "COM17" 
    }, 
    { 
    "$type": "OPCMessagingService.LED, OPCMessagingService", 
    "ResourceId": 75, 
    "DeviceIp": "10.142.117.6", 
    "ComPort": "COM13", 
    "IsMessageDelivered": false, 
    "RetryCount": 3, 
    "IsRetryRequired": true, 
    "_messageHeader": ":*HF601011471", 
    "_messageText": "XHC 9228 BULK - 0020 -投矿物油和橡胶、抗氧剂,升温", 
    "_delayedMessageText": "", 
    "_counter": 0 
    } 
], 
"UpdateDate": 20150120, 
"UpdateTime": 225331, 
"CurrentDate": 20150124, 
"CurrentTime": 151513, 
"CurrentMessage": "XHC 9228 BULK - 0020 -投矿物油和橡胶、抗氧剂,升温" 
} 
} 

내가 이것을 직렬화 할 수 있고 하나의 응용 프로그램에서 직렬화 할 수 있지만 분명히 다른 이름 공간이있는 다른 응용 프로그램에서 직렬화하려고 할 때. 예외가 발생했습니다.

JSON 'System.Collections.Generic.Dictionary`2 [System.Int32, mscorlib], [OPCMessagingService.Resource, OPCMessagingService], mscorlib'에 지정된 오류 유형을 확인하는 중입니다. 내가 시도 138

경로 '$ 유형', 1 호선, 위치는 다음을 수행하는 동안 다른 응용 프로그램에서 JSON 문자열을 직렬화하는 데 그것은 내가이 객체

를 직렬화 해제 할 수있는 그 밖의 무엇을 작동하지 않습니다
public static T GetRedisKeyValue<T>(string key) 
    { 
     if (key.Trim().Length > 0) 
     { 
      GetSentinelMaster(); 
      using (ConnectionMultiplexer redisClient = ConnectionMultiplexer.Connect(GetRedisConfiguraion())) 
      { 
       IDatabase redisDB = redisClient.GetDatabase(); // Getting database connection 
       string temp = redisDB.StringGet(key); 
       Type type = typeof(T); 
       JObject jsonObject = JObject.Parse(temp); 
       jsonObject["$type"] = type.FullName + ", " + type.Assembly.FullName; 
       // JsonConvert.DeserializeObject<T>(temp); 
       return JsonConvert.DeserializeObject<T>(temp, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Objects, TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Full }); 
      } 
     } 
     return default(T); 
    } 

이 작업을 수행하려면 어떻게해야합니까?

+0

내가 serialize하고 직렬화하는 개체 유형은 Dictionary 유형입니다. 리소스에는 장치 목록과 기본 유형 인 각 장치가 있으며 각 장치는 LED 또는 StackLight 중 하나 일 수 있습니다. –

+0

왜 전체 네임 스페이스를 직렬화 하시겠습니까? –

+0

어떻게 내가 다음과 같은 방식으로 serialize하는 것을 피할 수 있습니까? 'JsonConvert.SerializeObject (value, new JsonSerializerSettings {TypeNameHandling = TypeNameHandling.Objects})' 더 좋은 방법이 있나요? ..? –

답변

1

"$type"의 형식은 송신 시스템의 CLR 네임 스페이스를 포함하기 위해 공식적으로 hardcoded입니다. 그래서, 당신은 다음 중 하나를 수행 할 수 있습니다

  1. 는 송신 시스템의 것과 일치하도록 CLR 네임 스페이스의 이름을 변경하거나

  2. 서브 클래스 DefaultSerializationBinder과에 설정하여 직렬화하는 동안 CLR 네임 스페이스 이름을 이름을 변경하는 데 사용할 JsonSerializerSettings.Binder. 당신이 당신의 JSON 직렬화 할 때

    다음
    public class NamespaceMappingSerializationBinder : DefaultSerializationBinder 
    { 
        public string FromNamespace { get; set; } 
    
        public string ToNamespace { get; set; } 
    
        public override Type BindToType(string assemblyName, string typeName) 
        { 
         string fixedTypeName; 
         if (FromNamespace != null && ToNamespace != null) 
         { 
          fixedTypeName = typeName.Replace(FromNamespace, ToNamespace); 
         } 
         else 
         { 
          fixedTypeName = typeName; 
         } 
         var type = base.BindToType(assemblyName, fixedTypeName); 
         return type; 
        } 
    } 
    

    은, 그래서 같이 JsonSerializerSettingsBinder을 설정 :

    JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Objects, Binder = new NamespaceMappingSerializationBinder { FromNamespace = "From Namespace", ToNamespace = "Your Namespace" } }; 
    

    유형

다음은이 일에 첫 번째 컷입니다 위의 구문 분석은 매우 조잡합니다. 나는 더 똑똑한 파서를 여기에서 발견했다 : How to parse C# generic type names?. 사용자 정의 Binder을 확장 사전을 매핑해야 할 수도 있습니다.

마찬가지로 직렬화에서 네임 스페이스 이름을 다시 매핑해야하고 .Net 4.0 이상에서 작동하는 경우 BindToName을 무시할 수 있습니다.

+1

문제를 해결할 수있었습니다.데이터를 serialize 할 필요가있는 클래스에 대한 새로운 클래스 라이브러리를 만들었고이를 두 응용 프로그램 모두에 대한 참조로 추가했습니다. 이렇게하면 내 응용 프로그램 모두에서 동일한 .NET 형식이 처리되며 매력적으로 작동합니다. –