Что-то похожее на "использование", которое создаст объект и вызовет метод, когда это будет сделано, но позвольте мне сделать то, что я хочу между ними
Я использую 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
, так есть ли другой общий способ, если вы реализуете такие функции? Я не ищу невероятно сложное решение, так как это просто поддержка для меня, поэтому у меня нет проблем с повторением кода для каждого сообщения. Но мне любопытно, есть ли забавный трюк С#, о котором я не знаю.
Ответы
Ответ 1
Да, вы можете легко обеспечить такую временную взаимосвязь между некоторыми вызовами, получив делегат, который содержит пользовательские действия, и вызывая этот делегат именно тогда, когда вы хотите.
Вот пример:
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);
});
По существу, это форма инверсия управления: практика, посредством которой общая часть кода вызывает внешнюю, специализированную фрагмент кода в указанной точке.
Как правило, это достигается с помощью (часто абстрактных) классов или интерфейсов - и совершает через них виртуальные вызовы. Делегаты и lambdas просто позволяют вам выражать одно и то же более кратко, в то время как компилятор выполняет скучную работу (например, объявляет новый класс, захватывая требуемые переменные) за кулисами.
Ответ 2
Создайте обертку вокруг класса 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);
}
}
Затем вы можете использовать его через using
:
var data = 123;
using (var msg = new AutoMessage(Client, Client.Connections))
{
msg.Message.Write(data);
}
Другой вариант - создать интерфейс IMessage
, который имеет определения методов для Encode
и Decode
, и разрешить другим классам реализовывать их. Затем создайте метод Send
, который будет писать тип сообщения и запустить метод Encode
. Это то, что я делаю с собственными приложениями, и он отлично работает.