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

时间:2015-09-05 22:14:47

标签: c# using maintainability

我使用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);

我想做类似的事情:

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

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

2 个答案:

答案 0 :(得分:21)

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

以下是一个例子:

import java.util.Scanner;

/**
 * Created on 9/5/15.
 * Following Reges, Stuart, and Martin Stepp. Building Java Programs: A Back to Basics Approach. 3rd Edition.
 * Chapter 4
 */

public class Ch4 {
    public static void main(String[] args) {
        hailstone_Sequence();
    }

    public static void hailstone_Sequence(){
        giveIntro();
        Scanner user_console = new Scanner(System.in);
        System.out.println("Please provide a starting integer: ");
        int BEGINVALUE = user_console.nextInt();
//        System.out.println("Please provide an ending integer: ");
//        int ENDVALUE = user_console.nextInt();
        System.out.println("Thank you. How long would you liked the sequence to be?");
        int STEPS = user_console.nextInt();
        System.out.println("Calculating..");
        compute_Hailstone_Sequence(BEGINVALUE, STEPS);
    }

    public static int compute_Hailstone_Sequence(int begin_num, int steps){
        System.out.print(begin_num + " ");
        for (int i = 1; i <= steps; i++ ){
            int x;
            if ((begin_num & 1) == 0 ){
//                even
//                int x = 0;
                x = (begin_num / 2);
                System.out.print(x + " ");
//                return x;
            }
            else {
//                int x = 0;
                x = (3 * begin_num + 1);
                System.out.print(x + " ");
//                return x;
            }
            return x;
        }
        return begin_num;
    }
}

这样称呼:

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

基本上,这是inversion of control的一种形式:一般代码段在指定点调用外部提供的专用代码段的实践。

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

答案 1 :(得分:7)

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

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的方法定义,并允许其他类实现它们。然后创建一个Send方法,该方法将编写消息类型并运行Encode方法。这就是我用我自己的应用程序做的事情,它很有用。