使用ServiceStack OrmLite为动态类型创建键值表

本文关键字:创建 键值 类型 动态 ServiceStack OrmLite 使用 | 更新日期: 2023-09-27 18:25:11

我想在数据库中按照的行创建一个键值表

public class KeyValue { 
    public string Id { get; set; }
    public dynamic Value {get; set; }
}

使用稍微修改过的SqlProvider,我可以让CreateTable<KeyValue>()生成varchar(1024) Idvarchar(max) Value

我保存对象到它没有问题。问题是当我加载对象时

var content = dbConn.GetById<KeyValue>("about");

此时的content.Value是一个字符串。

查看数据库记录,值的文本似乎没有存储任何类型信息。

除了手动调用ServiceStack.Text并使用适当的类型信息调用反序列化之外,我真的能做得更好吗?

我不需要绝对的动态,我的实际用例是使用基类而不是动态的多态性。所以我真的不在乎Value是什么类型,它是基类、动态的、对象等。不管是使用类

public class KeyValue { 
    public string Id { get; set; }
    public MySpecificChildType Value {get; set; }
}

除了Value的字符串之外,我一直无法获取其他任何内容。我可以告诉OrmLite序列化类型信息以正确地反序列化我的对象吗?还是我只需要手动执行?

编辑:一些进一步的信息。OrmLite使用ServiceStack.Text.TypeSerializer定义的Jsv序列化程序,在BSD版本中是不可插入的。如果我用动态值将Type属性添加到KeyValue类中,我可以进行

var value = content.Value as string;
MySpecificChildType strongType = 
                TypeSerializer.DeserializeFromString(content, content.Type);

我只是真的想要一个更好的方法来做这件事,我真的不喜欢一个1类型的对象进入数据库,然后用不同的类型(字符串)返回。

使用ServiceStack OrmLite为动态类型创建键值表

我没有使用JsvSerializer,但使用JsonSerializer可以实现这一点(通过几种不同的方式),并且从ServiceStack 4.0.11开始,您可以选择使用Json序列化程序,请参阅https://github.com/ServiceStack/ServiceStack/blob/master/release-notes.md#v4011-发行说明。

示例

public abstract class BaseClass {
    //Used for second example of custom type lookup
    public abstract string Type { get; set; }
}
public class ChildA : BaseClass {
    //Used for second example of custom type lookup
    public override string Type { get; set; }
    public string PropA { get; set; }
}

然后,在init/bootstrap类中,您可以配置序列化程序来发出正确反序列化所需的类型信息:

public class Bootstrapper {
    public void Init() {
        ServiceStack.Text.JsConfig.ExcludeTypeInfo = false;
        ServiceStack.Text.JsConfig.IncludeTypeInfo = true;
    }
}

如果您希望使用ServiceStack使用的默认"__type"属性以外的其他属性(例如,如果您希望有一个友好的名称来标识类型,而不是名称空间/程序集),您也可以将自己的自定义类型查找配置为

public class Bootstrapper {
    public void Init() {
        ServiceStack.Text.JsConfig.ExcludeTypeInfo = false;
        ServiceStack.Text.JsConfig.IncludeTypeInfo = true;
        ServiceStack.Text.JsConfig.TypeAttr = "type";
        ServiceStack.Text.JsConfig.TypeFinder = type =>
        {
            if ("CustomTypeName".Equals(type, StringComparison.OrdinalIgnoreCase))
            {
                return typeof(ChildA);
            }
            return typeof(BaseClass);
        }
    }
}