我正在构建一系列类,以尝试从主线代码中减少特定类类型的手动编码.
无论我看哪种方式总是需要手动编写特定类类型.
我希望我可以使用反射/激活器等能够使用构造函数中完成的工作来返回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仅用作默认模型的代理).