2017-12-08 9 views
1

인터페이스를 감안할 때 인터페이스 매개 변수 (C#을, MVC)를받을 때 다른 데이터베이스 스키마를 사용하지만 동일한 작업을 수행해야합니다. 팀이 새로운 앱을 작성하는 동안 오래된 앱을 유지 관리해야합니다. 요구 사항에는 두 라이브러리 모두 동일한 라이브러리를 사용하므로이 문제점이 존재합니다. 애플 리케이션은 모두 동일한 외부 API를 호출하고, 그 호출은 자신의 정적 클래스에 있고과 같이 액세스 할 수 있습니다 : 그래서,역 직렬화는

result.add(JsonConvert.DeserializeObject<IObject>(Convert.ToString(d))); 

휴식

분명히
public static IEnumerable<IObject> List(Guid listUniqueIdentifier) 
{ 
     //a custom class to call the API 
     using (var cmd = new WebApiCommand()) 
     { 
           //custom enum 
      cmd.CommandType = ApiComType.GET; 
      cmd.Command = "ListObjects"; 
      cmd.Filter = listUniqueIdentifier.ToString(); 
      IEnumerable<object> data = cmd.Execute(); 
      var result = new List<IObject>(); 
      foreach(var d in data) 
      { 
       result.add(JsonConvert.DeserializeObject<IObject>(Convert.ToString(d))); 
      } 
      return result; 
     } 

} 

, 당신은 인터페이스를 인스턴스화 할 수 없습니다 . GUID를 사용하는 버전을 만들려고하지 않고 실패하는 경우 정수 버전을 사용하십시오. 그것도 조금 해킹되었을뿐만 아니라 정수를 사용하는 최신 DB이기 때문에 흐름 제어로 try 블록을 사용하는 것이 더 나쁠 수 있습니다. 각 유형에 대해 다른 메소드를 작성하지 않고 올바른 오브젝트 인스턴스 유형 (A 또는 B)로 역 직렬화 할 수 있습니까? 편집 : 내가 찾은 솔루션은 일반적으로 중 $ 형식을 serialize하거나 그렇지 않으면 직렬화하는 동안 인스턴스 형식을 저장하는 포함합니다. API가 타사 응용 프로그램에 연결되어 있고이 데이터를 저장할 수 없으므로 불가능합니다.

답변

0

내가 알 수있는 한, 귀하는 어떤 유형의 클래스를 직렬화할지 "d"를 식별 할 수있는 방법이 없다는 것입니다. (의사)

foreach(var d in data) 
    { 
     like if(Convert.ToString(d).All(char.IsDigit) && Convert.ToString(d).length <= Int32.MaxValue) 
     { 
      result.add(JsonConvert.DeserializeObject<A>(Convert.ToString(d))); 
     } 
     else 
     { 
      result.add(JsonConvert.DeserializeObject<B>(Convert.ToString(d))); 
     } 

    } 

편집 :이 당신이 준 제한된 정보와 최선의 방법이라고 생각합니다. 그렇지 않다면 데이터 호출 자체를 변경하는 것이 좋습니다. 가능한 경우 호출 응용 프로그램에 따라 WebAPI가 두 가지 데이터 집합을 제공 할 수 있습니다.

0

내가 생각할 수있는 한 가지 접근 방식은 처음에 비 직렬화 한 내부 도우미 클래스를 추가하고 거기에서 AB 개체를 생성하는 것입니다. 이 같은 (참고 : 귀하의 GUID 분리 문자없이 가정합니다.)

foreach(var d in data) 
{ 
    var temp = JsonConvert.DeserializeObject<Helper>(Convert.ToString(d))); 
    result.add(temp.GetAOrBObject()); 
} 
return result; 
1

당신은 인스턴스화 다음 ID의 유형을 감지하기 위해 사용자 정의 JsonConverter을 사용할 수 있으며, 직렬화 복원시 객체의 정확한 유형을 채울 :

internal class Helper 
{ 
    public string _name {get;set;} 
    public string _id {get;set;} 

    public IObject GetAOrBObject() 
    { 
     if (_id.Length == 32) // Assume GUID with no separator like '-' 
     { 
      return new A() { Name = _name, ID = Guid.Parse(_id) }; 
     } 
     else 
     { 
      return new B() { Name = _name, ID = int.Parse(_id) }; 
     } 
    } 
} 

그럼 당신이 당신의 루프에서 코드를 변경할 수 있습니다 :

01 :

class CustomIObjectConverter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return typeof(IObject).IsAssignableFrom(objectType); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     JObject jo = JObject.Load(reader); 
     IObject target; 
     if (jo["ID"].Type == JTokenType.Integer) 
     { 
      target = Activator.CreateInstance<A>(); 
     } 
     else // Guid 
     { 
      target = Activator.CreateInstance<B>(); 
     } 
     serializer.Populate(jo.CreateReader(), target); 
     return target; 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     throw new NotImplementedException(); 
    } 
} 

DeserializeObject()에의 인스턴스를 전달, 컨버터를 사용하려면

var converter = new CustomIObjectConverter(); 
... 
foreach(var d in data) 
{ 
    result.add(JsonConvert.DeserializeObject<IObject>(Convert.ToString(d), converter)); 
} 

다음은 개념을 증명할 수있는 짧은 데모입니다. https://dotnetfiddle.net/p2HzsL