类似于 "using" 的东西,它会创建一个对象并在完成后调用它的方法,但让我在两者之间做我想做的事

Something similar to "using" that will create an object and call a method on it when done, but let me do what I want in between

我正在使用 Lidgren,对于我发出的每一种新消息,我最终都会编写相同类型的代码。我正在创建一个 NetOutgoingMessage 的实例,运行 对它进行各种赋值调用,然后在完成后发送它。创建和发送是一样的,所以我想写一个包装器来为我做这件事,但它是 sealed class 而不是 IDisposable。我正在做的是这样的:

NetOutgoingMessage om = server.CreateMessage();

om.Write(messageType);
om.Write(data1);
om.Write(data2);

server.SendMessage(om, server.Connections, NetDeliveryMethod.UnreliableSequenced, 0);

我想做类似的事情:

using(AutoNetOutgoingMessage om(server, messageType, NetDeliveryMethod.UnreliableSequenced))
{
    om.Write(data1);
    om.Write(data2);
}

显然我做不到 using 那么,如果实现这样的功能,还有另一种常见的方法吗?我不是在寻找一个非常复杂的解决方案,因为这对我来说只是可维护性,所以我没有问题为每条消息重复我的代码。但是我很好奇是否有一个我不知道的有趣的 C# 技巧。

是的,您可以通过接收包含自定义操作的委托并在您需要时准确调用该委托,轻松地在某些调用之间强制实施这种时间关系。

这是一个例子:

void MyMethod(Server server, Action<NetOutgoingMessage> action)
{
    NetOutgoingMessage om = server.CreateMessage();
    action(om);
    server.SendMessage(om, server.Connections, NetDeliveryMethod.UnreliableSequenced, 0);     
}

这样称呼它:

MyMethod(server, om => {
    om.Write(data1);
    om.Write(data2);
});

本质上,这是inversion of control的一种形式:通用代码在指定点调用外部提供的专用代码的做法。

通常,这是使用(通常是抽象的)classes 或接口实现的,并通过它们进行虚拟调用。委托和 lambda 只是让你更简洁地表达同样的事情,而编译器在幕后做无聊的工作(比如声明新的 class,捕获所需的变量)。

围绕实现 IDisposable 的 NetOutgoingMessage class 创建一个包装器。

public class AutoMessage : IDisposable
{
    private const NetDeliveryMethod method = NetDeliveryMethod.UnreliableSequenced;

    public NetPeer Peer { get; private set; }

    public List<NetConnection> Recipients { get; private set; } 

    public NetOutgoingMessage Message { get; private set; }

    public AutoMessage(NetPeer peer, List<NetConnection> recipients)
    {
        Peer = peer;
        Recipients = recipients;
        Message = peer.CreateMessage();
    }

    public void Dispose()
    {
        Peer.SendMessage(Message, Recipients, method, 0);
    }
}

然后您可以通过using使用它:

var data = 123;
using (var msg = new AutoMessage(Client, Client.Connections))
{
    msg.Message.Write(data);
}

另一种选择是创建一个接口 IMessage,其中包含 EncodeDecode 的方法定义,并允许其他 class 实现它们。然后创建一个 Send 方法来写入消息类型和 运行 Encode 方法。这就是我对自己的应用程序所做的,并且效果很好。