views:

141

answers:

2

I'm trying to write some activities with C# instead of the designer and XAML. VS2010 has been buggy and very slow for that, and it also has very poor compilation support (for variables names, properties and so on).

So I'm trying to create activities by inheriting from the Activity class directly, but I'm encountering a snag.

Here's my code:

public class TestActivity : Activity
{
    public InArgument<string> Username { get; set; }
    public InArgument<string> Password { get; set; }
    public OutArgument<bool> ValidCredential { get; set; }
    public OutArgument<ProvisioningRole> Role { get; set; }
    public OutArgument<Guid> Guid { get; set; }

    protected override Func<Activity> Implementation
    {
        get
        {
            return () =>
                {
                    return new Sequence()
                    {
                        Activities =
                        {
                            new AuthenticateUserActivity()
                            {
                                Username = this.Username,
                                Password = this.Password,
                                Guid = this.Guid,
                                Result = this.ValidCredential
                            },
                            new If()
                            {
                                Condition = this.ValidCredential,
                                Then = new GetUserRoleActivity()
                                {
                                    Username = this.Username,
                                    Password = this.Password,
                                    Result = this.Role
                                }
                            },
                        }
                    };
                };
        }
        set { base.Implementation = value; }
    }
}

The problem is with the If(), the condition. It's supposed to be an InArgument, but this.ValidCredential is an OutArgument. I've tried creating a Variable, assign the value of ValidCredential to it. I also tried to put the result of AuthenticateUserActivity in the variable and then assign it to ValidCredential, but I get an error saying the To property of Assign needs to be specified.

I've looked around for proper tutorials, but all I found was an MSDN article that had a quick and dirty code implementation, and it used literals instead of the passed arguments, so no help from there.

A: 

You should be able to get this to work. The basic approach should be to use a Variable to store data, use an OutArgument to get data out of activities into the Variable and InArguments to get data from a Variable into an activity.

Also note that the expressions to tie InArguments to Variables are VisualBasicValue expressions. So something like:

Condition = new VisualBasicValue("System.DateTime.Now.Hour < 12")

This blog post isn't about using arguments and variables but shows a couple of examples.

Maurice
A: 

I found out how to do it. You just need to create new InArgument from the original one. There is a constructor that takes an expression for it.

Username = new InArgument<bool>((ActivityContext c) => this.ValidCredential.Get(c))

So I changed my whole activity to

return new CompensableActivity()
{
    Body = new Sequence()
    {
        Activities =
            {
                new AuthenticateUserActivity()
                {
                    Username = this.Username.In(),
                    Password = this.Password.In(),
                    Guid = this.Guid.Out(),
                    Result = this.ValidCredential.Out()
                },
                new If(this.ValidCredential.In())
                {
                    Then = new GetUserRoleActivity()
                    {
                        Username = this.Username.In(),
                        Password = this.Password.In(),
                        Result = this.Role.Out()
                    },
                    Else = new Assign<ProvisioningRole>()
                    {
                        To = this.Role.Out(),
                        Value = ProvisioningRole.User
                    }
                }
            }
    },
};

In and Out being extension methods I wrote:

public static class WorkflowExtensions
{
    #region In
    public static InArgument<T> In<T>(this InArgument<T> self)
    {
        return new InArgument<T>(context => self.Get(context));
    }

    public static InArgument<T> In<T>(this OutArgument<T> self)
    {
        return new InArgument<T>(context => self.Get(context));
    }
    #endregion

    #region Out
    public static OutArgument<T> Out<T>(this InArgument<T> self)
    {
        return new OutArgument<T>(context => self.Get(context));
    }

    public static OutArgument<T> Out<T>(this OutArgument<T> self)
    {
        return new OutArgument<T>(context => self.Get(context));
    }
    #endregion
}

And now all is well!

Sefyroth