我正在开发一种解决方案,它将连接到各种服务器以读取数据和执行操作。 有许多变量使可靠通信复杂化,例如防火墙,停止/失败服务,身份验证差异和各种软件配置。 我可以使用一些方法来解决这些问题,但在执行时不知道哪些方法会成功。

我的目标是创建一个可用于执行操作的接口和实现。 第一个方法调用将是最快的实现,它适用于大多数设备,然后是其他可以处理前面列出的问题的调用。

在一个完美的世界中,将编写该过程以快速识别哪种方法会成功,但在我的测试中,处理时间与仅仅捕获异常一样多。 虽然性能始终是一个考虑因素,但最终成功完成任务更为重要。

下面是我创建的一个示例,它演示了迭代实现列表的最坏情况。 虽然这适用于一种方法,但在20或更多不同操作中使用时,它不遵循DRY原则。 一种可能的解决方案是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;
        }
    }
}

===============>>#1 票数:1

您可以将处理操作实现为通用扩展方法,您可以传递对单个项执行处理的方法:

public static int ProcessItems<T>(this IEnumerable<T> items, Func<T, int> processMethod)
{
    foreach (var item in items)
    {
        try
        {
            return processMethod(item);
        }
        catch(Exception) {}
    }
    return -1;
}

现在您已经考虑了项目的实际类型以及用于处理的方法。 唯一“固定”的是泛型方法的结果类型,它是一个整数。

对于您当前的示例,您可以这样调用它:

List<IProcess> implementations = ...;
int processResult = items.ProcessItems(x => x.ProcessItem(workType));

===============>>#2 票数:0 已采纳

您可以在第二个界面中使用TryParse模式:

public interface IProcess
{
    int ProcessItem(string workType);
}

internal interface ITryProcess
{
    bool TryProcessItem(string workType, out int result);
}

public class ProcessImplementation1 : ITryProcess
{
    public bool TryProcessItem(string workType, out int result)
    {
        result = -1;
        return false;
    }
}

public class ProcessImplementation : IProcess
{
    public int ProcessItem(string workType)
    {
        var implementations = new List<ITryProcess>();
        implementations.Add(new ProcessImplementation1());
        // ...
        int processId = -1;
        foreach (ITryProcess implementation in implementations)
        {
            if (implementation.TryProcessItem(workType, out processId))
            {
                break;
            }
        }
        if (processId < 0)
        {
            throw new InvalidOperationException("Unable to process.");
        }
        return processId;
    }
}

===============>>#3 票数:0

这里有一个类似于@BrokenGlass创建的解决方案,如果你想要一些非常简单和“通用”的东西。

public void TryAllImplementations<TService>(
    IEnumerable<TService> services,
    Action<TService> operation,
    Action<Exception> exceptionHandler = null)
{
    int dummy = 0;
    TryAllImplementations(
        services, 
        svc => { operation(svc); return dummy; },
        exceptionHandler);
}

public TReturn TryAllImplementations<TService, TReturn>(
    IEnumerable<TService> services, 
    Func<TService, TReturn> operation,
    Action<Exception> exceptionHandler = null)
{
    foreach (var svc in services)
    {
        try
        {
            return operation(svc);
        }
        catch (Exception ex)
        {
            if (exceptionHandler != null)
                exceptionHandler(ex);
        }
    }
    throw new ProgramException("All implementations have failed.");
}

由于我看到Unity标记,您可以使用服务接口在容器上使用ResolveAll<TService>()来获取所有实现。 将它与此代码相结合,您可以在IUnityContainer上执行类似扩展方法的IUnityContainer

public static class UnityContainerExtensions
{
    public static void TryAllImplementations<TService>(
        this IUnityContainer container,
        Action<TService> operation,
        Action<Exception> exceptionHandler = null)
    {
        int dummy = 0;
        container.TryAllImplementations<TService, int>(
            svc => { operation(svc); return dummy; },
            exceptionHandler);
    }

    public static TReturn TryAllImplementations<TService, TReturn>(
        this IUnityContainer container,
        Func<TService, TReturn> operation,
        Action<Exception> exceptionHandler = null)
    {
        foreach (var svc in container.ResolveAll<TService>())
        {
            try
            {
                return operation(svc);
            }
            catch (Exception ex)
            {
                if (exceptionHandler != null)
                    exceptionHandler(ex);
            }
        }
        throw new ProgramException("All implementations have failed.");
    }
}

以下是使用它的方法:

IUnityContainer container;

// ...

container.RegisterType<IProcess, ProcessImplementation1>();
container.RegisterType<IProcess, ProcessImplementation2>();
container.RegisterType<IProcess, ProcessImplementation3>();

// ...

container.TryAllImplementations(
    (IProcess svc) => svc.ProcessItem(workType),
    ex => Console.WriteLine(
        "  Failed: {0} - {1}.",
        ex.GetType(), 
        ex.Message));

  ask by Robert translate from so

未解决问题?本站智能推荐:

1回复

跨多个解决方案实施依赖注入

我们拥有15种解决方案,其中每个解决方案都包含许多自己的项目。 但是,所有解决方案都共享一个称为“模型”的通用项目。 但是,由于每个解决方案都连接其自己的对象图,因此这将导致Model项目的注册重复15次。 防止这种重复的最佳方法是什么? 例: 解决方案 模型
1回复

如何使用Unity Dependecy Injection Web API实施策略/门面模式

如何告诉Unity.WebApi依赖注入框架,在正确的控制器中注入正确的类? DI项目容器 -MVC项目- 控制器1: 控制器2:
1回复

使用Unity配置文件,如何在其他程序集中的混凝土中注册FluentValidation Validator实施

我正在尝试使用Unity配置文件注册FluentValidation.IValidator的实现。 验证程序的实现在引用的程序集中。 不知道这是否重要。 我有一个WCF主机,带有2个引用(为简单起见) WCFHost.dll ParameterInspector.d
1回复

尝试将接口映射到Unity中的类类型时出现问题

问题背景: 我只是在设置一个Unity容器对象,注册所选接口的类型和继承该接口的类,然后尝试返回其实现。 编码: 统一: 界面-ITfsVcPromotionManager: 继承上述接口的类-TfsVcPromotionManager 错误信息:
1回复

尝试使用标记接口失败,IEnumerable <>

我试图在我自己的应用程序中使用统一来模仿Orchard CMS中的一些东西。 好的,我想要做的就是这...... 假设我有一个名为IDependency的标记接口.. 然后,我有几个接口挂在这... 然后也有一些课程...... 到目前为止我有什么..
1回复

依赖注入:-尝试创建“ controller”类型的控制器时发生错误

控制器: 错误: InvalidOperationException:尝试创建类型为Travelers.eBusiness.RiskQuiz.Web.Controllers.DisplayController的控制器时发生错误。 确保控制器具有无参数的公共构造函数 经
1回复

尝试获取ICacheManager类型的实例时出现激活错误,键“缓存管理器”

我似乎在这里遇到了障碍,并希望得到任何能够在这一方面得到帮助的人。 我不确定下面的错误消息是什么意思。 我正在使用企业模式服务的缓存块,但我继续遇到下面的问题。 我下载了最新版本,并尝试逐步解决这个问题,但我似乎无法解决确切的问题,我需要帮助。 提前致谢
1回复

尝试在WebApi(Net Framework)中使用IoC容器时出错

我正在尝试在WebApi模板中使用IoC容器。 我创建了一个空的Web App Framework项目,并选择使用WebApi。 然后,我添加了Unity NuGet包,并将以下内容添加到Application_Start: UnityConfig: 我的UnityResol
2回复

实施通用工厂

我正在尝试为可插拔接口设计工厂。 这个想法是,一旦有了工厂实例,工厂将为该特定实现返回适当的子类。 在这种情况下,我包装了一个第三方库,该库使用String来表示ID代码,而不是子类。 因此,在包装其库的实现中,每个实现类都具有接口API并未明确要求的getCode()方法。 我使用
1回复

Unity错误-尝试获取IUserRepository类型的实例(键“”)时发生激活错误

我正在尝试运行从Codeplex下载的MVC示例项目Shrinkr 我实际上在VS2012中打开了此解决方案,并且正在成功编译。 但是,当我运行此应用程序时,出现此错误。 我收到一条异常错误消息,指出“尝试获取类型为IUserRepository,键为“”的实例时发生激活错误