2017-12-08 6 views
1

インターフェイスを考えます異なるデータベーススキーマを使用しますが、同じ作業を行います。これは、チームが新しいものを書いている間、古いアプリを維持する問題です。要件には、両方とも同じライブラリを使用することが含まれているため、この問題が存在します。アプリケーションは両方とも同じ外部APIを呼び出し、その呼び出しは、独自の静的クラスであるので、同じようにアクセスされる:そう、デシリアライズインタフェースパラメータ(C#の、MVC)を受け入れながら

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)に逆シリアル化できますか?編集:私が見つけた解決策は通常、$型をシリアル化するか、そうでなければシリアル化中にインスタンスの型を保存することです。 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は可能な限り呼び出し側アプリケーションに応じて2つの異なるデータセットを提供できます。

0

私が考えることのできるアプローチの1つは、まずデシリアライズする内部ヘルパークラスを追加し、そこからABオブジェクトを生成することです。このようなもの(注:GUIDに区切り文字がないと仮定しています)。

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) }; 
     } 
    } 
} 

次に、あなたはこれにあなたのループ内のコードを変更することができます。

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

あなたはIDのタイプを検出するためのカスタムJsonConverterを使用して、直列化復元時にオブジェクトの正しい型をインスタンス化して取り込むことができます:

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

関連する問題