不要将基类Trigger
上的isMet()
方法设为抽象方法,而是将其设为虚拟
方法,可能的默认值为false。然后,您可以在派生类中使用override
关键字重写该方法。
您的第二个问题涉及将触发器序列化和反序列化到数据库中。在反序列化时,您需要确保获取的是派生触发器类型,而不是基本类型。我不知道您选择了什么方法将对象序列化到数据库中,但您需要一种存储类型的方式。以为例。它将一个作为其第一个参数。如果您在序列化触发器时将typeof(DerivedTrigger)存储到数据库中的另一个字段中,那么您可以反序列化Type并使用它来将Trigger反序列化为正确的派生类型。然后调用您的isMet()方法应该调用派生重写值。这里是一个使用静态变量代替数据库的简短示例:
[DataContract]
partial class Trigger
{
public virtual bool isMet()
{
return false;
}
}
[DataContract]
class DerivedTrigger : Trigger
{
public object DataElement1 { get; set; }
public override bool isMet()
{
return true;
}
}
void Main()
{
DerivedTrigger t = new DerivedTrigger();
Serialize(t);
((Trigger)Deserialize()).isMet();
}
public static void Serialize<T>(T source)
{
MemoryStream ms = new MemoryStream();
Type serializedObjectType = typeof(T);
DataContractSerializer dcsObject = new DataContractSerializer(serializedObjectType, null, int.MaxValue, false, true, null);
dcsObject.WriteObject(ms, source);
byte[] buffer = new byte[1024]
ms.Position = 0;
ms.Read(buffer, 0, 1024);
ms.Position = 0;
DataContractSerializer dcsType = new DataContractSerializer(typeof(Type), null, int.MaxValue, false, true, null);
dcsType.WriteObject(ms, serializedObjectType.DeclaringType);
buffer = new byte[1024]
ms.Position = 0;
ms.Read(buffer, 0, 1024);
}
public static object Deserialize()
{
MemoryStream ms = new MemoryStream();
byte[] buffer = new byte[1024];
ms.Write(buffer, 0 1024);
ms.Position = 0;
DataContractSerializer dcsType = new DataContractSerializer(typeof(Type), null, int.MaxValue, false, true, null);
Type serializedObjectType = dcs.Read(ms);
DataContractSerializer dcs = new DataContractSerializer(serializedObjectType, null, int.MaxValue, false, true, null);
return dcs.ReadObject(serializedObject);
}
编辑
好的,使用MemoryStream似乎让情况变得混乱了。MemoryStream不是存储在数据库中的内容,它本身就是数据库。
有serializedObjectType
的整个原因是因为,像你所说的,使用typeof(Trigger)
作为DataContractSerializer中的类型无法反序列化实际上是派生触发器的对象。因此,您需要将派生类型与对象一起存储在数据库中。
您没有说您正在使用哪种dbms,但我会使用blob来表示Trigger列,并使用varbinary或blob来表示serializedObjectType
列,即Trigger的实际最终派生类型。使用硬编码类型序列化程序对类型进行序列化。即DataContractSerializer(typeof(Type), ...)
,并使用DataContractSerializer(typeof(T), ...)
对对象进行序列化,其中T是可以使用泛型类型变量获取的派生触发器类型。
当您反序列化时,要倒序执行。首先使用硬编码的类型序列化程序(例如DataContractSerializer(typeof(Type), ...))反序列化类型,然后使用反序列化类型的结果反序列化对象。我已经更新了我的代码片段,希望更好地说明我提出的策略。抱歉回复晚了。
通常,在讨论序列化时,您只序列化对象中的值,因为这是一个对象与另一个对象之间的区别所在。您不需要将方法体序列化到数据库中,因为它存储在文件系统中的程序集中(即您在问题中提到的可插入的dll)。加载这些dll是一个完全不同的步骤。请查看System.Reflection.Assembly.LoadFile()。
从您问题中的这两个语句中:
触发器和操作需要存储在数据库中。
...用户可以将自己的自定义触发器派生类作为DLL放入指定的文件夹中。
我假设(也许不正确)类的定义将存储在文件系统上,而进入每个类对象的数据将存储在数据库中。如果您派生的
isMet()
方法是静态的(可能没有明确说明,但没有任何相关状态),那么在数据库中将没有任何东西可供存储。然而,听起来你正在设置一个
Trigger
持有一组
Actions
。在这种情况下,这些
Actions
被序列化到数据库中。如果您的类是
Serializable
,则将它们标记为公共的,否则直接将集合标记为
Serializable
。然后,内存流的大小将与每个触发器所持有的
Actions
数量成比例。清楚吗?