WF。 NativeActivity中的C#表达式

时间:2013-04-24 13:43:52

标签: expression workflow-foundation

我正在尝试在NativeActivity中使用自定义c#表达式

它可以通过简单的表达式工作,例如 Condition = new CSharpValue(“1 == 1”)

它不适用于此类表达式 Condition = new CSharpValue(“Address == null”)

由于表达式编译错误,我无法在表达式中引用活动的变量或InArgument“当前上下文中不存在名称'xxxxx'”

工作代码

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

非工作代码(指NativeActivity的InArgument)

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

帮助方法

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 个答案:

答案 0 :(得分:1)

错误很明确;您的表达式在范围内没有变量MailAddressVar

原因是你需要将变量传递给表达式。 ExecuteIfTrue活动没有变量参数。

请尝试以下方式:

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