Рефакторинг шаблона командC#

Место общения программистов C#
Ответить
Гость
 Рефакторинг шаблона команд

Сообщение Гость »

Я реализовал шаблон команды для SDK, который создаю на C#, но хочу предотвратить его неправильное использование. На данный момент у меня есть (1). Обратите внимание, что метод Execute запроса можно вызвать напрямую, минуя логику метода Execute SDK:

Код: Выделить всё

 public partial class Sdk
{
public async Task Execute1(ICommandRequest1 commandRequest)
where TOut : ICommandResponse1
{
// validation logic and other logic goes here
return await commandRequest.Execute1(this);
}
}

public interface IRequest1 { }
public interface IResponse1 { }
public interface ICommandResponse1 : IResponse1 { }

public interface ICommandRequest1 : IRequest1
where TOut : ICommandResponse1
{
Task Execute1(Sdk sdk);
}

public class DeleteOrderResponse1 : ICommandResponse1
{
public int OrderNum { get; set; }
}

// there are many request objects. this one is for deleting orders.
public class DeleteOrderRequest1 : ICommandRequest1
{
public int OrderNum { get; set; }

public async Task Execute1(Sdk sdk)
{
// logic goes here

return await Task.FromResult(new DeleteOrderResponse1()); // example response
}
}

public class TestItOut1
{
public async Task Test()
{
var sdk = new Sdk();
var request = new DeleteOrderRequest1 { OrderNum = 1 };
var response = await sdk.Execute1(request); // correct usage

// I do not want to allow this, because it bypasses all the logic in the
// sdk.Execute1() method
var response2 = request.Execute1(sdk);
}
}
Поэтому я подумал, что можно попробовать отделить запрос от его выполнения (2). Но это более громоздко - здесь гораздо больше деталей, которых мне хотелось бы не иметь, и особенно мне не нравится необходимость приводить общий inputRequest к типу внутри нового метода Execute2, а затем приводить вернитесь еще раз для возвращаемого типа.

Код: Выделить всё

 public partial class Sdk
{
public async Task Execute2(ICommandRequest2 commandRequest)
where TOut : class, ICommandResponse2
{
// validation logic and other logic goes here
return await new CommandExecutor2().Execute2(commandRequest, this);
}
}

public interface IRequest2 { }
public interface IResponse2 { }
public interface ICommandResponse2 : IResponse2 { }

public interface ICommandExecutor2 : IRequest2
where TOut : ICommandResponse2
{
Task Execute2(ICommandRequest2 request, Sdk sdk);
}

public interface ICommandRequest2 : IRequest2
where TOut : ICommandResponse2
{
//note: no longer contains the Execute method - good
}

public class DeleteOrderResponse2 : ICommandResponse2
{
public int OrderNum { get; set; }
}
public class DeleteOrderRequest2 : ICommandRequest2
{
public int OrderNum { get; set; }
}

// there are many command executors. this one is for deleting orders.
// note: internal - so clients outside the SDK cannot access this
internal class CommandExecutor2 : ICommandRequest2, ICommandExecutor2
where TOut : class, ICommandResponse2
{
public async Task Execute2(ICommandRequest2 inputRequest, Sdk sdk)
{
// I don't like having to do a cast here
DeleteOrderRequest2 request = inputRequest as DeleteOrderRequest2;

// logic goes here

// I also don't like having to do a cast here
return (await Task.FromResult(new DeleteOrderResponse2())) as TOut; // example response
}
}

public class TestItOut2
{
public async Task Test()
{
var sdk = new Sdk();
var request = new DeleteOrderRequest2 { OrderNum = 1 };
DeleteOrderResponse2 response = await sdk.Execute2(request);

// this no longer works - good - clients will not be able to bypass the validation logic
// var response2 = request.Execute2(sdk);
}
}
Есть ли у кого-нибудь лучшие идеи решения проблемы? Я не хочу использовать операторы отражения или if/switch. В идеале я бы хотел, чтобы CommandExecutor2 использовал конкретные типы DeleteOrderRequest2 и DeleteOrderResponse2, но пока мне с этим не повезло.

Подробнее здесь: https://stackoverflow.com/questions/787 ... nd-pattern
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»