在 CosmosDB 集合中,我有两种类型的实体,它们继承自一个基类。 我想从规范返回基类,并能够将该基类对象转换为具体对象。 我不使用 EF,我使用 CosmosDB SDK。 我想要这样的东西:
class BaseClass
{
string Id;
}
class ClassA : BaseClass
{
string Status;
}
class ClassB : BaseClass
{
string Amount;
}
public class MyScpec : Specification<BaseClass>
{
public MyScpec ()
{
Query.Select(x =>
(x is ClassA
? new ClassA { Id = x.Id, Status = x.Status }
: new ClassB { Id = x.Id, Amount = x.Amount}
));
}
}
进一步在代码中我希望能够这样做:
var list = _repository.List(new MySpec());
foreach(var item in list)
{
if(item is ClassA) { ...}
}
我尝试返回 BaseClass:
Query.Select(new BaseClass(){...})
但是我无法将其转换为子类。
另外,我尝试做类似 EF 中的事情,当我们可以配置实体时
builder.HasBaseType<BaseClass>();
但据我所知,CosmosDB SDK 中不存在这种可能性。
我找到了解决方案。你需要有一个自定义的 json 转换器
public abstract class AbstractJsonConverter<T> : JsonConverter
{
protected abstract T? Create(Type objectType, JObject jObject);
public override bool CanConvert(Type objectType)
{
return typeof(T).IsAssignableFrom(objectType);
}
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
{
return null;
}
var jObject = JObject.Load(reader);
if (jObject.Type == JTokenType.Null)
{
return null;
}
var target = Create(objectType, jObject);
serializer.Populate(jObject.CreateReader(), target!);
return target;
}
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
serializer.Serialize(writer, value);
}
}
public class DataModelConverter : AbstractJsonConverter<DataModelBase>
{
protected override DataModelBase Create(Type objectType, JObject jObject)
{
switch (jObject[nameof(DataModel.id)]!.Value<string>())
{
case var id when id!.StartsWith("typeOne"):
return new DataModelOne();
case var id when id!.StartsWith("typeTwo"):
return new DataModelTwo();
default:
throw new ArgumentException();
}
}
}