Я разрабатываю решение, которое будет подключаться к широкому кругу серверов для чтения данных и выполнения операций. Существует много переменных, которые усложняют надежную связь, такие как брандмауэры, остановленные / отказавшие службы, различия в аутентификации и различные конфигурации программного обеспечения. Существуют методы, которые я могу использовать, чтобы обойти эти проблемы, хотя во время выполнения неизвестно, что окажется успешным.
Моя цель - создать интерфейс и реализации, которые можно использовать для выполнения операций. Первый вызов метода будет самой быстрой реализацией, которая работает для большинства устройств, за которой следуют другие вызовы, которые могут решить проблемы, перечисленные ранее.
В идеальном мире был бы написан процесс, позволяющий быстро определить, какой метод будет успешным, но в моих тестах это занимало столько же времени обработки, сколько простое обнаружение исключения. Хотя производительность всегда учитывается, в конце концов, более важно, чтобы задача была успешно завершена.
Ниже приведен пример, который я создал, который демонстрирует наихудший сценарий, повторяющийся в списке реализаций. Хотя это хорошо работает для одного метода, он не следует принципу СУХОГО при использовании в 20 или более различных операциях. Одним из возможных решений является Unity и Interception, но я обнаружил, что метод invoke в обработчике вызовов использует разрешенную реализацию, а не список возможных реализаций. Если я что-то упустил, это не вариант. Кроме того, мне нужно будет следовать этому шаблону для нескольких интерфейсов, поэтому было бы неплохо создать универсальный обработчик, который может перебирать список реализаций.
Любой совет о том, как выполнить эту задачу, будет принят!
Интерфейс
public interface IProcess
{
int ProcessItem(string workType);
}
Реализация
public class ProcessImplementation1 : IProcess
{
public int ProcessItem(string workType)
{
throw new TimeoutException("Took too long");
}
}
public class ProcessImplementation2 : IProcess
{
public int ProcessItem(string workType)
{
throw new Exception("Unexpected issue");
}
}
public class ProcessImplementation3 : IProcess
{
public int ProcessItem(string workType)
{
return 123;
}
}
Специальная реализация перебирает другие реализации, пока одна из них не завершится успешно
public class ProcessImplementation : IProcess
{
public int ProcessItem(string workType)
{
List<IProcess> Implementations = new List<IProcess>();
Implementations.Add(new ProcessImplementation1());
Implementations.Add(new ProcessImplementation2());
Implementations.Add(new ProcessImplementation3());
int ProcessId = -1;
foreach (IProcess CurrentImplementation in Implementations)
{
Console.WriteLine("Attempt using {0} with workType '{1}'...",
CurrentImplementation.GetType().Name, workType);
try
{
ProcessId = CurrentImplementation.ProcessItem(workType);
break;
}
catch (Exception ex)
{
Console.WriteLine(" Failed: {0} - {1}.",
ex.GetType(), ex.Message);
}
Console.WriteLine();
if (ProcessId > -1)
{
Console.WriteLine(" Success: ProcessId {0}.", ProcessId);
}
else
{
Console.WriteLine("Failed!");
}
return ProcessId;
}
}
}