WF. C# expressions inside of NativeActivity

≯℡__Kan透↙ 提交于 2019-12-22 10:27:27

问题


I am trying to use custom c# expression inside of NativeActivity

It works fine with simple expression like Condition = new CSharpValue("1 == 1")

It doesn't work with such expressions Condition = new CSharpValue("Address == null")

I cannot refer to the activity's Variable or InArgument in the expression due to expression compilation error "The name 'xxxxx' does not exist in the current context"

Working code

var act = new ExecuteIfTrue
{
    Condition = new CSharpValue<Boolean>("1 == 1"),
    Address = new InArgument<MailAddress>(ctx => new MailAddress { DisplayName = "TestDisplayName" }),
    Body = new WriteLine { Text = "Rest!" }
};

CompileCSharpExpressions<MailAddress>(act);
WorkflowInvoker.Invoke(act);

Non-Working code (refers to the InArgument of NativeActivity)

var act = new ExecuteIfTrue
{
    Condition = new CSharpValue<Boolean>("Address.Email == null"),
    //Condition = new CSharpValue<Boolean>("MailAddressVar == null"),
    Address = new InArgument<MailAddress>(ctx => new MailAddress { DisplayName = "TestDisplayName" }),
    Body = new WriteLine { Text = "Rest!" }
};

CompileCSharpExpressions<MailAddress>(act);
WorkflowInvoker.Invoke(act);

NativeActivity

public class ExecuteIfTrue : NativeActivity
{
    [RequiredArgument]
    public InArgument<bool> Condition { get; set; }

    [RequiredArgument]
    public InArgument<MailAddress> Address { get; set; }

    public Variable<MailAddress> MailAddressVar;

    public Activity Body { get; set; }

    public ExecuteIfTrue()
    {
        MailAddressVar = new Variable<MailAddress> { Default = null };
    }

    protected override void Execute(NativeActivityContext context)
    {
        if (context.GetValue(this.Condition) && this.Body != null)
            context.ScheduleActivity(this.Body);
    }

    protected override void CacheMetadata(NativeActivityMetadata metadata)
    {
        metadata.AddImplementationVariable(MailAddressVar);
        base.CacheMetadata(metadata);
    }
}


public class MailAddress
{
    public String Email { get; set; }
    public String DisplayName { get; set; }
}

Helper method

public static void CompileCSharpExpressions<T>(Activity activity)
{
    var impl = new AttachableMemberIdentifier(typeof(TextExpression), "NamespacesForImplementation");
    var namespaces = new List<string> { typeof(T).Namespace };
    TextExpression.SetReferencesForImplementation(activity, new AssemblyReference { Assembly = typeof(T).Assembly });
    AttachablePropertyServices.SetProperty(activity, impl, namespaces);

    var activityName = activity.GetType().ToString();
    var activityType = activityName.Split('.').Last() + "_CompiledExpressionRoot";
    var activityNamespace = string.Join(".", activityName.Split('.').Reverse().Skip(1).Reverse());

    var settings = new TextExpressionCompilerSettings
    {
        Activity = activity,
        Language = "C#",
        ActivityName = activityType,
        ActivityNamespace = activityNamespace,
        RootNamespace = null,
        GenerateAsPartialClass = false,
        AlwaysGenerateSource = true,
        ForImplementation = false
    };

    var results = new TextExpressionCompiler(settings).Compile();

    if (results.HasErrors)
    {
        throw new Exception("Compilation failed.");
    }

    var compiledExpressionRoot = Activator.CreateInstance(results.ResultType, new object[] { activity }) as ICompiledExpressionRoot;
    CompiledExpressionInvoker.SetCompiledExpressionRoot(activity, compiledExpressionRoot);
}

回答1:


The error is pretty explicit; your expression does not have the variable MailAddressVar in scope.

The reason being is you need to pass the variable into the expression. The ExecuteIfTrue activity does not have a variables parameter.

Instead try something like this:

Variable<string> mailAddressVar = new Variable<string>(name: "MailAddressVar", defaultValue: null);

Activity seq = new Sequence
{
    Variables = { mailAddressVar },
    Activities = 
    {
        new ExecuteIfTrue
        {       
            //Condition = new CSharpValue<Boolean>("Address.Email == null"),
            Condition = new CSharpValue<Boolean>("MailAddressVar == null"),
            Address = new InArgument<MailAddress>(ctx => new MailAddress { DisplayName = "TestDisplayName" }),
            Body = new WriteLine { Text = "Rest!" }
        }
    }
};

ExecuteIfTrue.CompileCSharpExpressions<MailAddress>(seq);
WorkflowInvoker.Invoke(seq);


来源:https://stackoverflow.com/questions/16193628/wf-c-sharp-expressions-inside-of-nativeactivity

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!