通用通信框架的模式(处理和公开接收到的数据)

本文关键字:数据 处理 通信 框架 模式 | 更新日期: 2023-09-27 17:50:38

我目前正在开发一个基于套接字的通用通信"框架"的实现,该框架可以在c#和Android之间工作。

构建服务器和客户端非常容易。没有什么技术上的挑战。

此时实现包含两个主要组件:

AndroidTcpListener (tcp套接字类处理通信)
AndroidTcpServer(类创建TcpListener的实例和处理DataReceived(来自TcpListener)当接收到数据时)

数据在客户端和服务器使用标准XML序列化器(我可能在某些时候转向JSON)点,但目前我没有

我似乎完全卡住的地方是如何处理和暴露接收到的数据。

我尝试过使用泛型,但无论我如何构造它,似乎最终我不得不创建一个AndroidTcpServer<T>,然后将我限制为单一数据类型。

我已经尝试创建一个CustomActivator类,如

class CustomActivator<T> where T : Serialization.ITcpSerializable<T>
{
    public CustomActivator(String xmlTypeName, Byte[] data) 
    {
        this.XmlTypeName = xmlTypeName;
        this.Data = data;
    }
    public String XmlTypeName { get; set; }
    public Byte[] Data { get; set; }
    public T Activate()
    {
        T res =  Activator.CreateInstance<T>();
        using (MemoryStream stream = new MemoryStream(this.Data))
        {
            return res.Deserialize(XElement.Load(stream));               
        }
    }
}

但这似乎又限制了我实现AndroidTcpServer<T>

我已经尝试创建一个AndroidTcpEvent类,其结构如下

public class AndroidTcpEvent<T>
{
    public AndroidTcpEvent() { }
    public AndroidTcpEvent(String eventName, T data)
    {
        this.EventName = eventName;
        this.Data = data;
    }
    public String EventName { get; set; }
    public T Data { get; set; }
}

但是XMLSerializer似乎拒绝序列化它(我想我可以实现我自己的序列化器,但这远非微不足道,并不能真正解决我将如何暴露数据)

我已经尝试了无数其他的方法,但似乎都在某个地方陷入了死胡同。

现在我在AndroidTcpServer类里面有一个方法

private void DataReceived(Object sender, TcpServerMessageReceivedEventArgs e)
{
    //e.Data = Byte[] of XML serialized data of the message sent (Semantics are unimportant)
}

总之,我希望有一些指导,如何通常处理暴露数据接收和实际创建数据的实例在这样一个通用框架,如果有任何已知的模式,可以用于这个问题?

显然,我可以刮掉所有这些通用实现的东西,只是创建一个自定义实现的任何应用程序,我最终试图建立,但我这样做既是一个学习练习,我想向公众发布的东西,让其他人使用。

希望我已经说清楚了,但如果有人需要澄清这方面的任何方面,请让我知道。提前感谢大家的参与

通用通信框架的模式(处理和公开接收到的数据)

首先,我认为服务器的责任应该以引发TcpServerMessageReceived事件结束。它的任务是监听传入的连接并接收数据,然后通知任何感兴趣的人。

然后你可以将你的自定义激活器附加到该事件上,可能像这样:

class CustomActivator<T> where T : Serialization.ITcpSerializable<T>
{
    public void ListenTo(AndroidTcpServer server)
    {
         server.TcpServerMessageReceived += DataReceived;
    }
    private void DataReceived(object sender, TcpServerMessageReceivedEventArgs e)
    {
        T res =  Activator.CreateInstance<T>();
        using (MemoryStream stream = new MemoryStream(e.Data))
        {
            OnObjectReceived(res.Deserialize(XElement.Load(stream));               
        }
    }
    protected void OnObjectReceived(T obj)
    {
        var handler = ObjectReceived;
        if (handler != null)
        {
            OnObjectReceived(this, new ObjectReceivedEventArgs(obj));
        }
    }
}

我不确定您通过网络发送的对象类型。如果您可以在实际需要反序列化整个对象之前确定序列化xml中包含的类型,那么您可以修改CustomActivator,以便它检查类型并忽略它,如果它不是自己的T(希望这有意义),并且您可以为您可以接收的每种类型附加激活器(也许您可以使用反射来附加实现ISerializable接口的所有类型自动)。

Update:如果你能从传入的数据中猜出类型,你可以这样做:

class GenericActivator
{
    public void ListenTo(AndroidTcpServer server)
    {
         server.TcpServerMessageReceived += DataReceived;
    }
    private void DataReceived(object sender, TcpServerMessageReceivedEventArgs e)
    {
        var t = Type.GetType(GuessTypeName(e.Data));
        var res =  Activator.CreateInstance(t) as typeof(ITcpSerializable<>).MakeGenericType(t);
        using (MemoryStream stream = new MemoryStream(e.Data))
        {
            OnObjectReceived(res.Deserialize(XElement.Load(stream));               
        }
    }
    protected void OnObjectReceived(object obj)
    {
        var handler = ObjectReceived;
        if (handler != null)
        {
            OnObjectReceived(this, new ObjectReceivedEventArgs(obj));
        }
    }
}

您还可以在GenericActivator中添加一个类型注册表,以便为每种类型注册侦听器,如下所示:

class GenericActivator
{
     private Dictionary<Type, List<Action<object>> _TypeListeners;
     public void Register<T>(Action<object> objectReceived)
     {
         List<Action<object>> listeners;
         if (!_TypeListeners.TryGet(typeof(T), out listeners)
         {
             listeners = new List<Action<object>>();
         }
         listeners.Add(objectReceived);
     }
}

然后只调用接收到的类型的侦听器。假设GuessTypeName工作可靠