.net 在工厂中订阅事件处理程序

.net 在工厂中订阅事件处理程序,.net,dependency-injection,factory,.net,Dependency Injection,Factory,我正在编写一个VB.Net应用程序,它需要通过TCP套接字接收消息,但我的问题实际上与套接字无关。为了简单起见,假设我想创建一个类,该类处理来自Socket类事件的数据,Socket类是我们公司创建的类库的一部分。在研究依赖注入时,他说不要将套接字实例注入到消息处理器的构造函数中,这样处理器就可以订阅事件。相反,我应该给处理器一个公共函数,让组合根创建一个套接字和处理器,并从套接字连接处理程序,以便它调用处理器上的公共函数。一开始效果很好 但现在我遇到了一个需要动态创建和处理套接字的情况。上述技

我正在编写一个VB.Net应用程序,它需要通过TCP套接字接收消息,但我的问题实际上与套接字无关。为了简单起见,假设我想创建一个类,该类处理来自Socket类事件的数据,Socket类是我们公司创建的类库的一部分。在研究依赖注入时,他说不要将套接字实例注入到消息处理器的构造函数中,这样处理器就可以订阅事件。相反,我应该给处理器一个公共函数,让组合根创建一个套接字和处理器,并从套接字连接处理程序,以便它调用处理器上的公共函数。一开始效果很好

但现在我遇到了一个需要动态创建和处理套接字的情况。上述技术的问题在于,套接字、处理器和事件订阅将在应用程序的生命周期内有效。我想我可以使用工厂来创建processor对象。然后,工厂将创建一个套接字、处理器和订阅事件处理程序。但是它只将处理器返回给客户机,那么它如何取消订阅处理器呢?我不想因为未能取消订阅事件处理程序而导致泄漏

已更新

下面的代码是一个完整的控制台应用程序。希望我能在简单性和解释问题之间找到正确的平衡

导入System.Collections.Concurrent
模块1
副标题()
'创建连接
Dim ConnectionClient作为新ConnectionClient(新消息ConnectionFactory)
“做一些发送和接收
ConnectionClient.DoSomething()连接
'等待,以便用户可以查看结果
Console.WriteLine(“按任意键”)
Console.ReadLine()
端接头
端模块
公共类DataProducedEventArgs
继承事件参数
以字节()形式显示的公共属性数据
末级
公共类套接字
作为EventHandler生成的公共事件数据(属于DataProducedEventArgs)
'在实际应用程序中,当我们在套接字上接收数据时,事件将触发。
这提供了一种模拟的方法。
公共子模拟器接收数据(数据为字节())
RaiseEvent DataProducerd(Me,带有{.Data=Data}的新DataProducerDeventargs)
端接头
公共子发送(数据为字符串)
WriteLine(“通过套接字发送:{0}”,数据)
端接头
末级
公共类消息处理器
公共子消费(数据为字节())
WriteLine(“接收到的{0}字节数据”,data.Length)
端接头
末级
公共类消息发送者
专用插座作为插座
公共子新(插座作为插座)
_插座
端接头
公共子发送(消息为字符串)
_socket.Send(消息)
端接头
末级
公共类消息连接
作为MessageProcessor的公共属性处理器
作为MessageSender的公共属性发件人
末级
公共类连接客户端
私有工厂作为MessageConnectionFactory
私有连接作为新的ConcurrentQueue(属于MessageConnection)
公共子新建(工厂为MessageConnectionFactory)
_工厂
端接头
公共子剂量测量法()
“接通
将连接设置为MessageConnection=\u Factory.Create
“用它做点什么吧
Connection.Sender.Send(“测试”)
“TODO-我可以在这里处理,但那不行
'删除事件处理程序
端接头
末级
公共类MessageConnectionFactory
公共函数Create()作为MessageConnection
'创建对象
将MySocket调暗为新插座
将连接设置为新消息连接
Connection.Processor=newmessageprocessor
Connection.Sender=newmessagesender(MySocket)
“这个处理程序怎么可能被删除?
AddHandler MySocket.DataProducted,Sub(发送方,e)Connection.Processor.Consume(e.Data)
'客户端只关心消息连接对象,而不关心套接字
回路连接
端函数
末级

这对你有用吗

Public Class ConnectionClient

    Private _Factory As MessageConnectionFactory

    Public Sub New(factory As MessageConnectionFactory)
        _Factory = factory
    End Sub

    Public Sub DoSomething()
        _Factory.Using(Sub(c) c.Sender.Send("Test"))
    End Sub

End Class

Public Class MessageConnectionFactory
    Public Sub [Using](action As Action(Of MessageConnection))
        Dim MySocket As New Socket
        Dim Connection As New MessageConnection
        Connection.Processor = New MessageProcessor
        Connection.Sender = New MessageSender(MySocket)

        Dim handler = New EventHandler(Of DataProducedEventArgs)(Sub(sender, e) Connection.Processor.Consume(e.Data))
        AddHandler MySocket.DataProduced, handler
        action(Connection)
        RemoveHandler MySocket.DataProduced, handler
    End Sub
End Class

你能提供一份详细的报告吗?我可以在VB.NET控制台应用程序中复制、粘贴和运行的东西?我已将代码更新为可以粘贴到控制台应用程序并运行的东西。在实际应用程序中,有更复杂的机制用于创建和销毁连接。关键的一点是TODO,在这里事件处理程序应该真正被删除。事实上,套接字对象将永远存在。在实际系统中,MessageConnection对象是基于与其他硬件的连接而创建或销毁的,因此它比单个功能的持续时间更长。我这样写只是为了减少示例的复杂性。但我可能可以使用异步函数而不是操作来完成这项工作,该操作返回一个任务,该任务在连接完成后完成。让我玩一下,然后再打给你。@RobL-你可以让一个动作持续到你喜欢的时间。它最终有助于实施更具功能性的编码风格。当然,但如果我不使其异步,它将阻止调用方。@RobL-这是您第一次提到不想阻止调用方。使用异步函数并不妨碍您使用操作。事实上,你可以很好地将两者结合使用。这非常有效。我确实通过实验发现,大多数时候我并不需要这种复杂程度。事件订阅保存在套接字中,该套接字仅由发送方引用,而MessageConnection对象仅引用。所以为了摆脱它们,我只需要停止引用MessageConnection实例,GC就会(最终)删除套接字中的所有内容,这样就不会有泄漏。但我确实有一个例子,其中套接字是保留的,我需要动态地添加和删除订阅者。在这种情况下,上面的示例非常有效。谢谢