Я пытаюсь реорганизовать «доверенный фасад», который в настоящее время переносит более 50 вызовов службы на серверную часть. Все звонки имеют разные подписи, но все остальное повторяется. Проблема с существующими вызовами заключалась в том, что не было предпринято никаких попыток управлять соединениями, в результате чего эфемерные порты оставались в состоянии «BOUND».
ОРИГИНАЛЬНЫЙ КОД:
public class ReportWeb : IReportWeb
{
ReportService.ReportClient client = new ReportClient();
...
public string[] GetAccounts() => client.GetAccounts();
}
НОВЫЙ КОД:
private ChannelFactory<IReportService> _factory = null;
private IReportService _proxy = null;
private void OpenProxy()
{
_factory = new ChannelFactory<IReportService>("NetTcpBinding_IReportService");
_proxy = _factory.CreateChannel();
}
private void CloseProxy()
{
((IClientChannel)_proxy).Close();
_factory.Close();
}
Один из 50+ подобных методов:
public string[] GetAccounts() // Different - name, params, and return type
{
string[] accounts = null; // Different
try
{
OpenProxy();
accounts = _proxy.GetAccounts(); // Different
CloseProxy();
}
catch (Exception exception)
{
bool faulted = _factory.State == CommunicationState.Faulted;
_factory.Abort();
if (faulted)
{
throw new ApplicationException(exception.Message);
}
else
{
throw;
}
}
return accounts;
}
Еще один аналогичный метод:
//Another method
public ContractsInfo[] GetContracts(int contractId) // Different -
// name, params, and return type
{
ContractsInfo[] contracts = null; // Different
try
{
OpenProxy();
contracts = _proxy.GetContracts(contractId); // Different
CloseProxy();
}
catch (Exception exception)
{
bool faulted = _factory.State == CommunicationState.Faulted;
_factory.Abort();
if (faulted)
{
throw new ApplicationException(exception.Message);
}
else
{
throw;
}
}
return contracts;
}
Код вызова из проекта Web Forms:
public string[] GetAccounts()
{
ReportClient client = NewReportClient();
string[] results = null;
try
{
results = client.GetAccounts();
client.Close();
}
catch (Exception ex)
{
client.Abort();
throw ex;
}
return results;
}
Существует более пятидесяти других методов, таких как GetData(), с разными сигнатурами. Все они будут идентичны, за исключением вызова службы в каждом, который будет различаться параметрами и типом возвращаемого значения. Мне нужен более абстрактный или общий способ кодирования и, таким образом, придерживаться принципа DRY. Func<T, TResult> Delegate здесь уместно? В любом случае, может ли кто-нибудь предложить лучший подход здесь с некоторым кодом-заглушкой для иллюстрации?
Я полагаю, что это тот случай, когда можно применить общий метод с. это можно прочитать о дженериках здесь
Позвольте мне показать пример кода:
public class Foo
{
public T GetDate<T, UArg>(UArg arg) where T : new()
{
return new T();
}
}
Имеет смысл, за исключением того, что это тип фасада, и все его методы имеют разные имена, параметры и типы возвращаемых значений. Если бы я попытался пойти по этому пути, я бы изменил API, а затем также должен был бы изменить более 50 вызовов API в клиенте? Я обновил код, чтобы показать, что будет отличаться. Мысль, что использование Func<...> может сработать...
@IrishChieftain, не могли бы вы показать больше примеров различных методов, таких как GetData()?
Сделанный. Некоторые методы имеют три или четыре разных параметра и совершенно разные типы возвращаемых значений. Я попытался извлечь исключение из метода, но столкнулся с загадкой «выбросить или выбросить исключение».
@IrishChieftain Правильно ли я понял, что все эти 50 методов находятся в классе ReportWeb? Если да, можете ли вы опубликовать код, который вызывает эти методы?
Добавлен код вызова клиента.
@IrishChieftain спасибо за ваши обновления. Я полагаю, как вы сказали, можно использовать Func. Я думал, что здесь можно использовать шаблон Template, но это не тот случай, так как все 50 методов размещены в одном классе, и это требует огромного рефакторинга кода.
Есть ли какой-то процесс по этому вопросу.
@Jiayao, универсального решения не существует, так как многие методы имеют разные сигнатуры. Я отмечаю SetUp как правильный ответ, потому что он все еще может упростить проблему, имея интерфейс с набором функций, которые соответствуют тому, что необходимо.
Сухой принцип, о котором вы сказали, означает не повторяться, то есть не повторять одно и то же. У вас есть много методов, которые лишь немного отличаются друг от друга, поэтому вы хотите разработать общий способ уменьшить количество избыточности в вашем коде.