当我在设计时不知道POCO的确切类型,而我在运行时只得到Type时,如何使用ServiceStack中的OrmLite正确反序列化POCO?
所以,像这样:
// Returns the object and can be cast to the correct subobject
public BaseClass ReadObject(Type typeOfObject, int id)
{
using (var db = _dbFactory.Open())
{
baseObject = db.Select<BaseClass>(typeOfObject, id); // need something here...
return baseObject;
}
}
...
BaseClass bc = ReadObject(someType, 3); // someType = Customer for example
...
class BaseClass { ... }
class Actor : BaseClass { ... }
class Customer : Actor { ... }
class Operator : Actor { ... }
我坚持使用Actor和Customer,但是当我读回它们时,我基本上只有一个Type,可能还有主键。 .Select <>不起作用,因为我需要在运行时知道类型。
我发现这样: Create (and select from) a table dynamically using servicestack ormlite
如果我理解正确,那么在设计时获取类型未知的POCO的唯一方法是执行手动SQL语句,如答案所示:
var modelDef = employeeType.GetModelMetadata();
var tableName = db.GetDialectProvider().GetQuotedTableName(modelDef);
var sql = $"SELECT * FROM {tableName}";
var results = db.Select<List<object>>(sql);
var results = db.Select<Dictionary<string,object>>(sql);
var results = db.Select<dynamic>(sql);
但是,这不会创建顶部列出的任何类。我需要将其类型转换为BaseClass,但它当然应该是正确的对象(例如,“ Customer”,“ Operator”等)。
我该如何实现?
(我还指出,Mythz曾说过在持久化数据时使用继承是一个坏主意,他建议“拉平”层次结构。但是,我会伸出脖子说,面向对象的语言,继承和多态性是不可避免的,那里没有99.9%的编码人员可以消除;-))
答案 0 :(得分:2)
在OrmLite中使用运行时类型的支持非常有限。
请参见OrmLite's Untyped API Support,它使您可以在处理运行时类型时访问某些Insert, Update and Delete APIs。
但是SELECT需要指定要选择的具体类型,即,您可以使用以下方法选择基类:
var results = db.Select<BaseClass>(typeOfObject);
但是结果只会填充BaseClass
属性。
一种可能的解决方案是使用Dynamic Dictionary ResultSets API将结果选择到对象字典列表中,例如:
List<Dictionary<string,object>> results = db.Select<Dictionary<string,object>>(q);
然后使用FromObjectDictionary Reflection Utils将其转换为后期绑定类型,例如:
List<BaseClass> customers = results.Map(x => (BaseClass)x.FromObjectDictionary(customerType));
(我还注意到,Mythz曾说过在持久化数据时使用继承是一个坏主意,他建议“拉平”层次结构。但是,我会竭尽全力地说,在处理面向对象语言时,继承和多态性是不可避免的,那里没有99.9%的编码人员可以消除;-))
如果您要引用某人,请 verbatim ,包括指向您所引用来源的链接,因为这是对我所说内容的虚假陈述。
您可能会强烈推荐我的答案against using inheritance and base type properties and unknown late-bound types like interfaces and objects in DTOs。这是为了避免耦合到特定的序列化实现,并且是运行时序列化问题的主要根源,这与创建定义良好的可互操作服务的目标相反。您可以避免使用此指南,但是您的服务只能与特定的序列化程序实现一起使用,在不同的语言中失败,并且元数据支持有限,因为它们将无法使用未知类型来静态推断服务合同中的漏洞。
但是此引用与OrmLite中的继承无关,在OrmLite中,您的POCO可以愉快地具有任何级别的继承。问题是您要查询一个未知的后期绑定类型,因为OrmLite是带有类型化API的代码优先的ORM,需要访问具体类型以支持其类型化表达式API并填充其类型化结果。我在上面的回答包括OrmLite对无类型访问的有限支持。