我正在构建一系列类,以尝试从主线代码中减少特定类类型的手动编码. 无论我看哪种方式总是需要手动编写特定类类型. 我希望我可以使用反射/激活器等能够使用构造函数中完成的工作
无论我看哪种方式总是需要手动编写特定类类型.
我希望我可以使用反射/激活器等能够使用构造函数中完成的工作来返回classtypes(正确类型)而不需要做大(虽然这里的示例已经减少)选择/切换GetPacket中的语句.
我知道这是VB.Net,但该项目已经用该语言编写,我不介意如果你发布C#示例我只会转换它们.
但请不要将其作为VB.Net问题重新定位,因为它不是关于如何在框架内完成它的语言.
Imports ProtoBuf Public Class CompatiblePackets Inherits Dictionary(Of Packet.PacketType, Base) Public Sub New() Dim theAssembly As Assembly = Assembly.GetExecutingAssembly For Each t As Type In theAssembly.GetTypes If t.BaseType Is GetType(Base) Then Dim p As Base = CType(t.Assembly.CreateInstance(t.FullName), Base) Me.Add(p.PacketTypeIndicator, p) End If Next End Sub Public Function GetPacket(id As PacketType, data As Stream) As Base Dim activePacket As Base If Me.ContainsKey(id) Then activePacket = Me(id) Else activePacket = Me(PacketType.Generic) End If Try Select Case id Case PacketType.AcknowledgeBulk Return GetPacket(Of AcknowledgeBulk)(activePacket, data) Case PacketType.Generic Return GetPacket(Of Generic)(activePacket, data) Case PacketType.Identification Return GetPacket(Of Identification)(activePacket, data) '''There are so far about 20 more packet types in the real code. Case Else 'unknown type "Computer says No!" End Select Catch ex As Exception If data.GetType Is GetType(MemoryStream) Then Debug.Print(Core.Text.OutputData(CType(data, MemoryStream).ToArray)) End If Throw End Try Debug.Print("Wtf - " & id.ToString()) Return New NoOperation End Function Private Function GetPacket(Of t)(activePacket As Packet.Base, data As Stream) As t Return Serializer.Deserialize(Of t)(data) End Function End Class如果我正确理解了这个问题,看起来你应该使用Serializer.NonGeneric;这有多种方法可以手动传递Type而不使用泛型,包括Serialize和Deserialize.
请注意,对于此方案,Serializer.NonGeneric还具有用于异构标头标记消息的特定API,您可能会发现这对于网络流方案很有用:
static void Main() { // memory-stream only for example - would work fine with NetworkStream too using(var ms = new MemoryStream()) { // this is just to simulate an incoming network-stream Serializer.SerializeWithLengthPrefix(ms, new Foo { Name = "abc" }, PrefixStyle.Base128, 1); // tag 1 for Foo Serializer.SerializeWithLengthPrefix(ms, new Bar { Value = 123 }, PrefixStyle.Base128, 2); // tag 2 for Bar ms.Position = 0; // now we'll consume it //first setup some map of 1=Foo, 2=Bar - any mechanism will suffice var typeMap = new Dictionary<int, Type>{ {1, typeof(Foo)}, {2, typeof(Bar)} }; Serializer.TypeResolver resolver = i => { Type type; return typeMap.TryGetValue(i, out type) ? type : null; }; object obj; while(Serializer.NonGeneric.TryDeserializeWithLengthPrefix( ms, PrefixStyle.Base128,resolver,out obj)) { Console.WriteLine(obj); } Console.WriteLine("<EOF>"); } } [ProtoContract] class Foo { [ProtoMember(7)] public string Name{ get; set; } public override string ToString() { return "Foo: " + Name; } } [ProtoContract] class Bar { [ProtoMember(4)] public int Value { get; set; } public override string ToString() { return "Bar: " + Value; } }
这输出:
Foo: abc Bar: 123 <EOF>
在v2中,请注意TypeModel将非泛型API公开为主要接口(Serializer API仅用作默认模型的代理).