0

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

1 Answer 1

1

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();
Sign up to request clarification or add additional context in comments.

4 Comments

Its nice but the last statement requires it to be as a boolean which again performs some action . So can this be made as a fluent interface if required ?
@Joy which statement is last here?
Sorry apologies .I got your point. But can this be done without just handler1.SetNext(handler2.SetNext(handler3)); but with a fluent interface ? something like chaning setNext to do with as method chaining with conditions ? with outcome of one depending on the other ? I m really a novice in this architecture.
Wow awsome . !! something I requireed to have for a long time . I couldn't get a proper guidance when I had hit this roadblock . Thanks a lot !! :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.