我有一个项目,用户可以为其开发插件。在他们的插件中,他们必须扩展抽象基类。在我项目的核心中,动态加载插件(dll)并新建这些类。
代码核心中的基类:
[ProtoContract]
public abstract class BaseOutput
{
public string OutputName {get;}
[ProtoMember(1)]
public int X { get; set; }
}
插件示例(在其他项目中):
[ProtoContract]
public class MyOutput : BaseOutput
{
public override OutputName { get { return "MyOutput";} }
[ProtoMember(11)]
public double A { get; set; }
[ProtoMember(12)]
public double B { get; set; }
[ProtoMember(13)]
public double C { get; set; }
}
我知道必须在BaseOutput上添加 [ProtoInclude(10,typeof(MyOutput))] 但是当我开发应用程序的核心时,不知道该用户将被添加到程序中的插件。但是我想可以序列化所有类,并用protobuf扩展BaseOutput。
解决方案是什么?
答案 0 :(得分:3)
可以通过RuntimeTypeModel
API在运行时使用protobuf-net配置这种类型的关系,如下所示。但是:至关重要重要的是,每次应用运行时,所使用的密钥(在示例中为42
)都是可靠且确定的。含义:您需要每次都可靠地为您的特定插件类型 分别获取42
,无论有人是否添加/删除其他插件(这意味着:仅按字母顺序对其进行排序可能还不够)。另外:42
在所加载的不同插件之间必须唯一。
using ProtoBuf;
using ProtoBuf.Meta;
[ProtoContract]
public abstract class BaseOutput
{
public abstract string OutputName { get; }
[ProtoMember(1)]
public int X { get; set; }
}
[ProtoContract]
public class MyOutput : BaseOutput
{
public override string OutputName { get { return "MyOutput"; } }
[ProtoMember(11)]
public double A { get; set; }
[ProtoMember(12)]
public double B { get; set; }
[ProtoMember(13)]
public double C { get; set; }
public override string ToString()
=> $"A={A}, B={B}, C={C}"; // to show working
}
class Program
{
static void Main()
{
var pluginType = typeof(MyOutput); // after loading the plugin etc
var baseType = RuntimeTypeModel.Default[typeof(BaseOutput)];
baseType.AddSubType(42, pluginType);
BaseOutput obj = new MyOutput { A = 1, B = 2, C = 3 };
var clone = Serializer.DeepClone(obj);
// outputs: A=1, B=2, C=3 - so: working (yay!)
System.Console.WriteLine(clone.ToString());
}
}