如何实现可互换/可切换的业务逻辑

时间:2015-12-05 04:55:52

标签: c# .net

假设我有3项任务:注册,评估,注册。

我希望能够让我的应用程序在这个过程中具有这三个可互换的位置。因此,对于一个设置,我可以进行注册 - >评估 - >注册。我可以将其他设置更改为注册 - >注册 - >评定。

而且我还需要能够打开/关闭某些任务功能(如注册)。

你们能告诉我从哪里开始吗?

1 个答案:

答案 0 :(得分:2)

我会设置一个chain of responsibility。来自GoF:

  

通过为多个对象提供处理请求的机会,避免将请求的发送者耦合到其接收者。链接接收对象并沿链传递请求,直到对象处理它。

这是一个使用您已经提供的业务流程名称的准系统示例:

// These all should be named something relevant to your domain
public interface IHandler
{
    void Handle(string request);
}

public class Handler
{
    protected IHandler successor;

    protected Handler(IHandler successor)
    {
        this.successor = successor;
    }

    protected virtual void Successor(string request)
    {
        successor?.Handle(request);
    }
}

public class Registration : Handler, IHandler
{
    public Registration(IHandler successor) 
        : base(successor) { }

    public void Handle(string request)
    {
        Console.WriteLine($"Registration handled request {request}");
        base.Successor(request);
    }
}

public class Enrollment : Handler, IHandler
{
    public Enrollment(IHandler successor) 
        : base(successor) { }

    public void Handle(string request)
    {
        Console.WriteLine($"Enrollment handled request {request}");
        base.Successor(request);
    }
}

public class Assessment : Handler, IHandler
{
    public Assessment(IHandler successor) 
        : base(successor) { }

    public void Handle(string request)
    {

        if (request.Equals("Bob", StringComparison.InvariantCulture))
        {
            Console.WriteLine("Bob failed assessment.");
            return;
        }
        Console.WriteLine($"Assessment handled request {request}");
        base.Successor(request);
    }
}

和示例使用:

        // Consumers of this don't need to know anything more than it's an IHandler service
// Consumers of this don't need to know anything more than it's an IHandler service
IHandler noregistrationHandlers = new Assessment(new Enrollment(null));
// or Autofac
// builder.Register(c => new Assessment(c.Resolve<Enrollment>(null))).Named("NoRegistration");
// or your favorite IoC container
noregistrationHandlers.Handle("Smith");

IHandler registrationHandlers = new Registration(new Assessment(new Enrollment(null)));
// builder.Register(c => new Registration(c.Resolve<Assessment>(c.Resolve<Enrollment>(null)))).Named("Registration");
registrationHandlers.Handle("Bob");

以上是对此的讨论 - 消费代码(使用示例)除了将请求发送给处理程序的格式外,不需要知道任何内容。在示例中调用构造函数的事实仅仅是为了方便起见,例如。你很可能拥有一个依赖于IHandler的MVC控制器,但对此却一无所知。

public class UserController
{
    private readonly IHandler handler;

    public UserController(IHandler handler)
    {
        if (handler == null) throw new NullReferenceException(nameof(handler));

        this.handler = handler; 
    }

    // ...

    public ActionResult Save(string id)
    { 
        handler(id);
    }
}