I am trying to create a simple WF4 activity that takes a string containing a VB.NET expression (say a database), evaluates that string using the variables available in the current area of the workflow, and returns the result. Unfortunately, with the way I tried it, whether with a plain on Activityor full NativeActivity, I keep hitting the wall.
My first attempt was a simple Activity, and I was able to make a simple class that evaluates an expression, given that some object is its input:
public class Eval<T, TResult> : Activity<TResult>
{
[RequiredArgument]
public InArgument<T> Value { get; set; }
public Eval(string predicate)
{
this.Implementation = () => new Assign<TResult>
{
Value = new InArgument<TResult>(new VisualBasicValue<TResult>(predicate)),
To = new ArgumentReference<TResult>("Result")
};
}
public TResult EvalWith(T value)
{
return WorkflowInvoker.Invoke(this, new Dictionary<string, object>{ {"Value", value } });
}
}
This woks is beautiful, and the following expression evaluates to 7:
new Eval<int, int>("Value + 2").EvalWith(5)
, , , InArgument<string>, ( ) . , NativeActivity, :
public class NativeEval<T, TResult> : NativeActivity<TResult>
{
[RequiredArgument] public InArgument<string> ExpressionText { get; set; }
[RequiredArgument] public InArgument<T> Value { get; set; }
private Assign Assign { get; set; }
private VisualBasicValue<TResult> Predicate { get; set; }
private Variable<TResult> ResultVar { get; set; }
protected override void CacheMetadata(NativeActivityMetadata metadata)
{
base.CacheMetadata(metadata);
Predicate = new VisualBasicValue<TResult>();
ResultVar = new Variable<TResult>("ResultVar");
Assign = new Assign { To = new OutArgument<TResult>(ResultVar), Value = new InArgument<TResult>(Predicate) };
metadata.AddVariable(ResultVar);
metadata.AddChild(Assign);
}
protected override void Execute(NativeActivityContext context)
{
Predicate.ExpressionText = ExpressionText.Get(context);
context.ScheduleActivity(Assign, new CompletionCallback(AssignComplete));
}
private void AssignComplete(NativeActivityContext context, ActivityInstance completedInstance)
{
Result.Set(context, ResultVar.Get(context));
}
}
NativeEval :
WorkflowInvoker.Invoke(new NativeEval<int, int>(), new Dictionary<string, object>
{ { "ExpressionText", "Value + 2" }, { "Value", 5 } });
:
'1: NativeEval' , '1: NativeEval'. .
, metadata.AddVariable(ResultVar); metadata.AddImplementationVariable(ResultVar);, :
: "VariableReference": Variable (Name = 'ResultVar') . , , .
.ScheduleFunc(), , VisualBasicValue, null ( , , .)
. WF4 , System.Linq.Expressions, , (, ), , . , , , , , , , .
EDIT:. , , , , , , NativeActivity, :
Predicate = new VisualBasicValue<TResult>();
Predicate = new VisualBasicValue<TResult>("ExpressionText.Length");
Predicate.ExpressionText = ExpressionText.Get(context);
, , .
EDIT2: , . "" , :
metadata.AddVariable(ResultVar);
metadata.AddChild(Assign);
:
metadata.AddImplementationVariable(ResultVar);
metadata.AddImplementationChild(Assign);
. , , :
Predicate.ExpressionText = ExpressionText.Get(context);
ExpressionText VisualBasicValue . ILSpy , - , CacheMetadata(), , , no-op. NativeActivityMetadata, CacheMetadata, , VisualBasicValue CacheMetadata(), , ( " ". AmbiguousMatchException).
, . , , Eval NativeEval.