类似于"使用"的东西会创建一个对象并在完成时调用它的方法,但让我做我想要的

Dan*_*n B 15 c# maintainability using

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

NetOutgoingMessage om = server.CreateMessage();

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

server.SendMessage(om, server.Connections, NetDeliveryMethod.UnreliableSequenced, 0);
Run Code Online (Sandbox Code Playgroud)

我想做的事情如下:

using(AutoNetOutgoingMessage om(server, messageType, NetDeliveryMethod.UnreliableSequenced))
{
    om.Write(data1);
    om.Write(data2);
}
Run Code Online (Sandbox Code Playgroud)

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

The*_*kis 21

是的,您可以通过接收包含自定义操作的委托并在您需要时准确调用该委托来轻松地在某些调用之间强制执行此类时间关系.

这是一个例子:

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

像这样称呼它:

MyMethod(server, om => {
    om.Write(data1);
    om.Write(data2);
});
Run Code Online (Sandbox Code Playgroud)

从本质上讲,这是一种控制反转的形式:一般代码片段在指定点调用外部提供的专用代码片段的实践.

通常,这是使用(通常是抽象的)类或接口实现的 - 并通过它们进行虚拟调用.代理和lambdas只允许您更简洁地表达相同的事情,而编译器在幕后完成无聊的工作(如声明新类,捕获所需的变量).


Cyr*_*ral 7

NetOutgoingMessage实现IDisposable 的类周围创建一个包装器.

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以通过它来使用它using:

var data = 123;
using (var msg = new AutoMessage(Client, Client.Connections))
{
    msg.Message.Write(data);
}
Run Code Online (Sandbox Code Playgroud)

另一种选择是创建一个接口IMessage有方法定义为EncodeDecode,并允许其他类来实现它们.然后创建一个Send将写入消息类型并运行该Encode方法的方法.这就是我用自己的应用程序做的事情,效果很好.

  • 在`Dispose`中调用`SendMessage`时要小心:这意味着即使代码的主体导致异常,它也会被调用.这不是我想要/期望发生的行为. (2认同)