使用表达式和动作委托进行决策制定

时间:2013-11-23 08:21:00

标签: c# delegates func

我有一个实例,我是C#delegates,Func,Expression和action的新手。我想传递一个参数作为一个表达式,它将检查几个条件,然后它将返回或执行基于某些条件,提供类似这样的

 var result = Uow.GroupLicense.Set
                        .Join(Uow.UserGroup.Set, x => x.GroupGuid, y => y.GroupGuid, (GL, G) => new { G, GL })
                        .Join(Uow.Users.Set, x => x.G.UserGuid, y => y.UserGuid, (UG, U) => new { UG, U })
                        .SingleOrDefault(x => x.U.UserID == Username);

            if (result != null && result.UG.GL.IsActive && result.U.IsEnabled && !result.U.IsLocked)
            {
                SessionStorage.LoginAttempts = UpdateLoginAttempts(Username, true);
                SessionStorage.SessionID = HttpContext.Current.Session.SessionID;
                SessionStorage.LoginAttempts = 0;
                SessionStorage.UserName = Username;
                SessionStorage.ABBUserName = Username;
            }
            else if (!result.UG.GL.IsActive)
            {
                result.U.IsEnabled = false;
                result.U.IsLocked = true;
                Uow.Users.Update(result.U);
                Uow.Commit();
                ErrorMessage = "User License Expired";
            }
            else if (result.U.IsLocked)
            {
                ErrorMessage = "User is locked";
            }
            else if (!result.U.IsEnabled)
            {
                ErrorMessage = "User is disabled by administrator";
            }
            else
            {
               ErrorMessage = "User doesnt exist ";
            }

现在这是我的原始代码。我想根据两个类项条件将其转换为决策树。像这样的东西

 if this ->  Boolean result = EnsureLicense((x, y) => x.IsEnabled && y.IsActive);
   then do Action1 
   if This -> Boolean result = EnsureLicense((x, y) => !x.IsEnabled && y.IsActive);
   then do Action2 
   if This - > Boolean result = EnsureLicense((x, y) => !x.IsEnabled && y.IsLocked);
   then do Action3.

我不想把它切换成类似if else结构代码的多个if else和else if结构代码。如何处理这种策略,因为我无法进入切换案例。

我想用Actions和Expression以及Func委托来做。我想学习如何继续这种策略。

请指导我

1 个答案:

答案 0 :(得分:1)

这是带有动作和Func委托的解决方案,它们不使用if ... else结构。实际上这是一种Chain of Responsibility

public class LicenseHandler
{
    private readonly Func<GroupLicense, User, bool> predicate;
    private readonly Action action;
    private LicenseHandler nextHandler;

    public LicenseHandler(Func<GroupLicense,User, bool> predicate, Action action)
    {
        this.action = action;
        this.predicate = predicate;
    }

    public LicenseHandler SetNext(LicenseHandler handler)
    {
        nextHandler = handler;
        return this;
    }

    public void Handle(GroupLicense license, User user)
    {
        if (predicate(license, user))
        {
            action();
            return;
        }

        if (nextHandler != null)
            nextHandler.Handle(license, user);
    }
}

创建处理程序并将它们链接起来:

var handler1 = new LicenseHandler((l, u) => l.IsEnabled && u.IsActive, Action1);
var handler2 = new LicenseHandler((l, u) => !l.IsEnabled && u.IsActive, Action2);
var handler3 = new LicenseHandler((l, u) => !l.IsEnabled && u.IsLocked, Action3);

handler1.SetNext(handler2.SetNext(handler3));

处理看起来像

handler1.Handle(licence, user);

支持基于代理的代码而不是简单的if-else的人会接受我最深切的同情。

更新:如果你想要漂亮的流畅API,那么你可以创建构建器类,它将创建处理程序链:

public class LicenseHandlerBuilder
{
    private LicenseHandler root;
    private LicenseHandler current;

    private LicenseHandlerBuilder() { }

    public static LicenseHandlerBuilder CreateHandler(
        Func<GroupLicense, User, bool> predicate, Action action)
    {
        var builder = new LicenseHandlerBuilder();
        builder.root = new LicenseHandler(predicate, action);
        builder.current = builder.root;
        return builder;
    }

    public LicenseHandlerBuilder WithNext(
        Func<GroupLicense, User, bool> predicate, Action action)
    {
        var next = new LicenseHandler(predicate, action);
        current.SetNext(next);
        current = next;
        return this;
    }

    public LicenseHandler Build()
    {
        return root;
    }
}

用法:

var handler = LicenseHandlerBuilder
        .CreateHandler((l, u) => l.IsEnabled && u.IsActive, Action1)
        .WithNext((l, u) => !l.IsEnabled && u.IsActive, Action2)
        .WithNext((l, u) => !l.IsEnabled && u.IsLocked, Action3)
        .Build();