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

时间:2011-04-21 05:15:08

标签: c# xml sockets generics types

我目前是开发基于套接字的通用通信“框架”实现的一个很好的部分,该框架在C#和Android之间起作用。

构建服务器和客户端非常简单。对此没什么技术上的挑战。

此时,实现包含2个主要组件。

  

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

     

在客户端和客户端之间发送数据   服务器使用标准XML   序列化器(我可能会转向JSON)   指出但我暂时还是   确定XML)

我似乎完全陷入困境的是如何处理和公开收到的数据。

我尝试过使用泛型,但无论我如何构建它,似乎最终我不得不创建一个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)
}

总之,我希望得到一些指导,说明如何处理暴露收到的数据并在这样的通用框架中实际创建数据实例,以及是否有任何已知模式可用于此问题?

显然,我可以抓取所有这些通用实现的东西,只是为我最终尝试构建的任何应用程序创建一个自定义实现,但我这样做是一个学习练习和我希望向公众发布的内容使用。

希望我一直很清楚,但如果有人要求澄清这方面的任何方面,请告诉我。提前感谢每个人的意见。

1 个答案:

答案 0 :(得分:1)

首先,我认为服务器的责任应该以提升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以便它检查类型并忽略它(如果它不是它自己的{{1} (希望这很有意义)并为每个可以接收的类型附加激活器(也许你可以使用反射来自动附加实现T接口的所有类型)。

更新:如果您可以从传入数据中猜出类型,您可以执行以下操作:

ISerializable

您还可以向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); } } 可靠地运作。