Question

I have a instance and I am new to C# delegates , Func , Expression and action . I want to pass a parameter as an expression which would check for few conditions and then it would return or perform based on some conditions provided something like this

 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 ";
            }

Now this is my original code . I want to convert this into a decision tree based on two class item conditions . Something like this

 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.

I dont wanna switch it into something like If else structure code with multiple if else and else if structure code . How to proceed with this kind of strategy since I cannot put into switch case .

I want to do it with Actions and Expression and Func delegates . I want to learn how to proceed with this kind of strategy .

Please guide me

Was it helpful?

Solution

Here is solution with actions and Func delegates, which do not use if...else structure. Actually this is a kind of 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);
    }
}

Create handlers and chain them:

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));

Processing looks like

handler1.Handle(licence, user);

People, who will support delegate-based code instead of simple if-else, accept my deepest sympathy.

UPDATE: If you want nice fluent API, then you can create builder class, which will create handlers chain:

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;
    }
}

Usage:

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();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top