如何在编译时获取所有类继承类?

时间:2011-12-17 22:30:16

标签: c# inheritance

我正在尝试编写网络代码,自动将数据包序列化和反序列化为NetworkMessage

以下是NetworkMessage

的代码
public abstract class NetworkMessage : ISerializable
{
    public readonly NetworkClient Client;

    protected NetworkMessage(NetworkClient client)
    {
        this.Client = client;
    }

    public abstract void GetObjectData(SerializationInfo info, StreamingContext context);
}

这是示例NetworkMessageText

的代码
public class NetworkMessageText : NetworkMessage
{
    public static readonly Byte Id = 0x01;

    public readonly String Message;

    public NetworkMessageText(NetworkClient client, String message)
        : base(client)
    {
        this.Message = message;
    }

    public override void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("message", this.Message, typeof(String));
    }
}

现在,要反序列化,我需要在字典< Byte,Type>中查找Id,我在代码时注册了不同的ID。

这是为我做的NetworkMessagesIds课程

public static class NetworkMessageIds
{
    private static readonly Dictionary<Type, Byte> TypeIdDictionary = new Dictionary<Type, Byte>();
    private static readonly Dictionary<Byte, Type> IdTypeDictionary = new Dictionary<Byte, Type>(); 

    static NetworkMessageIds()
    {
        TypeIdDictionary.Add(typeof(NetworkMessageText), NetworkMessageText.Id);
        IdTypeDictionary.Add(NetworkMessageText.Id, typeof(NetworkMessageText));
    }

    public static Byte IdFromType(Type type)
    {
        return TypeIdDictionary[type];
    }

    public static Type TypeFromId(Byte id)
    {
        return IdTypeDictionary[id];
    }
}

我正在寻找的是一种为编译时继承NetworkMessage的每个类自动生成Id字节的方法。我可以在运行时使用Reflection来完成它,但后来我不知道我是否可以相信每次机器的ID都是相同的,并且对于像这样的东西使用Reflection似乎有点过分。

或者,欢迎使用具有相同结果的不同方法的建议,我基本上需要的是一个易于扩展的解决方案,其中“最终用户”只需要继承NetworkMessage以使其代码与网络一起工作溶液

1 个答案:

答案 0 :(得分:3)

而不是在编译时执行此操作,您可以在应用程序加载时执行此操作并缓存您找到或未找到的内容(我倾向于不允许运行时可扩展性)。以下是一些(未经测试的)代码,可以找到&#39; NetworkMessage&#39;的所有子代:

var knownMessageTypes = AppDomain.CurrentDomain.GetAssemblies().ToList().ForEach(a => a.GetTypes().ToList().Where(t => t.IsSubclassOf(typeof(NetworkMessage)));

然后,如果您创建一个属性以供NetworkMessage的任何子级使用以标识消息ID字节,您可以动态地发现可以使用哪些类型来反序列化消息。

[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple=false)]
public class NetworkMessageAttribute : Attribute
{
    public byte MessageID { get; set }
}

然后您可以按如下方式创建网络消息类型:

[NetworkMessage(MessageID = 0x01)]
public class ExampleNetworkMessage : NetworkMessage

我已经在几个不同的项目中成功使用了这个通用设计概念。


编辑:如果您真的希望实现上述设计目标,可以使用与上述代码类似的方法实现。只需将其放入一个控制台应用程序,该应用程序将生成一个消息定义列表文件,供您的应用程序读取,并将其设置为项目中的后期构建活动。