给定接口:
interface IObject
{
public string Name {get;set}
}
和以下对象:
class A: IObject
{
public string Name {get;set}
public int ID {get;set;}
}
class B: IObject
{
public string Name {get;set}
public Guid ID {get;set;}
}
我有两个使用不同数据库模式的消费应用程序,但要做相同的工作。这是维护旧应用程序的问题,而团队则写一个新应用程序。要求包括两者都使用相同的库,这就是为什么存在此问题的原因。应用程序都调用相同的外部API,并且该调用在其自己的静态类中,并且可以像这样访问:
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;
}
}
显然,您无法实例化接口,所以
result.add(JsonConvert.DeserializeObject<IObject>(Convert.ToString(d)));
断裂。我不想只尝试构建指导版本,如果它失败了,请使用整数版本。不仅有点骇客,而且是使用整数的新数据库,因此我会以更糟糕的方式使用try
块作为流控制。在不为每种类型编写不同的方法的情况下,如何对正确的对象实例类型(A或B)进行应对序列化?编辑:我发现的解决方案通常涉及序列化$类型或以其他方式保存序列化的实例类型。这是不可能的,因为API已连接到第三方应用程序并且无法存储此基准。
您可以使用自定义JsonConverter
检测ID的类型,然后在测试过程中实例化并填充正确的对象类型:
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
您的问题是,您无法通过" 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可以根据可能的情况为您提供两套不同的数据。
我能想到的一种方法是添加您首先值得注意的内部助手类,然后从那里生成您的 A
和 B
对象。这样的东西(注意:我假设您的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;