我正在尝试运行某个活动,但是我在运行时收到此错误:
表达式活动类型'CSharpValue`1'需要编译才能运行。请确保已编译工作流程。
查看单位测试输出我看到了:
30: WorkflowInstance "PatriarchActivity" Unhandled Exception Source "Assign<SortedList<IntContainer,SimpleData>>" Exception <System.NotSupportedException: Expression Activity type 'CSharpValue`1' requires compilation in order to run. Please ensure that the workflow has been compiled.
编译似乎运行正常。
我使用此页面中的代码来编译工作流程: http://msdn.microsoft.com/en-us/library/jj591618%28v=vs.110%29.aspx#CodeWorkflows
我不知道问题是什么,并且消息没有帮助,因为错误在于imho。是的,得到它,还没有编译,然后我该如何编译呢?
非常感谢您的解释。
我正在使用带有.net 4.5.1的visual 2013 update 4
这是一个小测试案例,我希望能够正确地突出问题。
namespace WFCS
{
public sealed class ActivityCompiler
{
private static readonly ActivityCompiler instance_ = new ActivityCompiler();
public static ActivityCompiler Instance
{
get
{
return instance_;
}
}
public SimpleActivity GetSimpleActivity()
{
SimpleActivity act = new SimpleActivity();
AttachableMemberIdentifier impl = new AttachableMemberIdentifier(typeof(TextExpression), "Namespaces");
AttachablePropertyServices.SetProperty(act, impl, ActivityCompiler.Instance.GetSimpleActivityNameSpaceList());
TextExpression.SetReferencesForImplementation(act, ActivityCompiler.Instance.GetSimpleActivityAssemblyReferenceList().ToList());
ActivityCompiler.Instance.Compile(act);
return act;
}
public Boolean Compile(Activity aActivity)
{
try
{
// activityName is the Namespace.Type of the activity that contains the
// C# expressions.
string activityName = aActivity.GetType().ToString();
// Split activityName into Namespace and Type.Append _CompiledExpressionRoot to the type name
// to represent the new type that represents the compiled expressions.
// Take everything after the last . for the type name.
string activityType = activityName.Split('.').Last() + "_CompiledExpressionRoot";
// Take everything before the last . for the namespace.
string activityNamespace = string.Join(".", activityName.Split('.').Reverse().Skip(1).Reverse());
// Create a TextExpressionCompilerSettings.
TextExpressionCompilerSettings settings = new TextExpressionCompilerSettings
{
Activity = aActivity,
Language = "C#",
ActivityName = activityType,
ActivityNamespace = activityNamespace,
RootNamespace = "CSharpExpression",
GenerateAsPartialClass = false,
AlwaysGenerateSource = true,
ForImplementation = false
};
// Compile the C# expression.
TextExpressionCompilerResults results =
new TextExpressionCompiler(settings).Compile();
// Any compilation errors are contained in the CompilerMessages.
if (results.HasErrors)
{
throw new Exception("Compilation failed.");
}
// Create an instance of the new compiled expression type.
ICompiledExpressionRoot compiledExpressionRoot =
Activator.CreateInstance(results.ResultType,
new object[] { aActivity }) as ICompiledExpressionRoot;
// Attach it to the activity.
CompiledExpressionInvoker.SetCompiledExpressionRoot(
aActivity, compiledExpressionRoot);
}
catch (Exception e)
{
string err = e.ToString();
return false;
}
return true;
}
public Boolean CompileDynamicActivity(Activity aDynamicActivity)
{
try
{
// activityName is the Namespace.Type of the activity that contains the
// C# expressions.
string activityName = aDynamicActivity.GetType().ToString();
// Split activityName into Namespace and Type.Append _CompiledExpressionRoot to the type name
// to represent the new type that represents the compiled expressions.
// Take everything after the last . for the type name.
string activityType = activityName.Split('.').Last() + "_CompiledExpressionRoot";
// Take everything before the last . for the namespace.
string activityNamespace = string.Join(".", activityName.Split('.').Reverse().Skip(1).Reverse());
// Create a TextExpressionCompilerSettings.
TextExpressionCompilerSettings settings = new TextExpressionCompilerSettings
{
Activity = aDynamicActivity,
Language = "C#",
ActivityName = activityType,
ActivityNamespace = activityNamespace,
RootNamespace = "CSharpExpression",
GenerateAsPartialClass = false,
AlwaysGenerateSource = true,
ForImplementation = true
};
// Compile the C# expression.
TextExpressionCompilerResults results =
new TextExpressionCompiler(settings).Compile();
// Any compilation errors are contained in the CompilerMessages.
if (results.HasErrors)
{
throw new Exception("Compilation failed in ActivityCompiler");
}
// Create an instance of the new compiled expression type.
ICompiledExpressionRoot compiledExpressionRoot =
Activator.CreateInstance(results.ResultType,
new object[] { aDynamicActivity }) as ICompiledExpressionRoot;
// Attach it to the activity.
CompiledExpressionInvoker.SetCompiledExpressionRootForImplementation(
aDynamicActivity, compiledExpressionRoot);
}
catch (Exception e)
{
string err = e.ToString();
throw e ;
}
return true;
}
private HashSet<AssemblyReference> GetSimpleActivityAssemblyReferenceList()
{
HashSet<AssemblyReference> ass = new HashSet<AssemblyReference>();
ass.Add(new AssemblyReference { Assembly = typeof(StringContainer).Assembly, AssemblyName = typeof(StringContainer).Assembly.GetName() });
ass.Add(new AssemblyReference { Assembly = typeof(IntContainer).Assembly, AssemblyName = typeof(IntContainer).Assembly.GetName() });
ass.Add(new AssemblyReference { Assembly = typeof(System.Runtime.Serialization.IExtensibleDataObject).Assembly, AssemblyName = typeof(IExtensibleDataObject).Assembly.GetName() });
return ass;
}
private HashSet<String> GetSimpleActivityNameSpaceList()
{
HashSet<String> ns = new HashSet<String>();
ns.Add(typeof(StringContainer).Namespace);
ns.Add(typeof(IntContainer).Namespace);
return ns;
}
public MotherActivity GetMotherActivity()
{
MotherActivity act = new MotherActivity();
AttachableMemberIdentifier impl = new AttachableMemberIdentifier(typeof(TextExpression), "NamespacesForImplementation");
AttachablePropertyServices.SetProperty(act, impl, ActivityCompiler.Instance.GetMotherActivityNameSpaceList());
TextExpression.SetReferencesForImplementation(act, ActivityCompiler.Instance.GetMotherActivityAssemblyReferenceList().ToList());
ActivityCompiler.Instance.CompileDynamicActivity(act);
return act;
}
private HashSet<AssemblyReference> GetMotherActivityAssemblyReferenceList()
{
HashSet<AssemblyReference> ass = new HashSet<AssemblyReference>();
ass.UnionWith(ActivityCompiler.Instance.GetSimpleActivityAssemblyReferenceList());
ass.Add(new AssemblyReference { Assembly = typeof(System.Runtime.Serialization.IExtensibleDataObject).Assembly, AssemblyName = typeof(IExtensibleDataObject).Assembly.GetName() });
return ass;
}
private HashSet<String> GetMotherActivityNameSpaceList()
{
HashSet<String> ns = new HashSet<String>();
ns.UnionWith(ActivityCompiler.Instance.GetSimpleActivityNameSpaceList());
return ns;
}
public PatriarchActivity GetPatriarchActivity()
{
PatriarchActivity act = new PatriarchActivity();
AttachableMemberIdentifier impl = new AttachableMemberIdentifier(typeof(TextExpression), "NamespacesForImplementation");
AttachablePropertyServices.SetProperty(act, impl, ActivityCompiler.Instance.GetPatriarchActivityNameSpaceList());
TextExpression.SetReferencesForImplementation(act, ActivityCompiler.Instance.GetPatriarchActivityAssemblyReferenceList().ToList());
ActivityCompiler.Instance.CompileDynamicActivity(act);
return act;
}
private HashSet<AssemblyReference> GetPatriarchActivityAssemblyReferenceList()
{
HashSet<AssemblyReference> ass = new HashSet<AssemblyReference>();
ass.UnionWith(ActivityCompiler.Instance.GetMotherActivityAssemblyReferenceList());
return ass;
}
private HashSet<String> GetPatriarchActivityNameSpaceList()
{
HashSet<String> ns = new HashSet<String>();
ns.UnionWith(ActivityCompiler.Instance.GetMotherActivityNameSpaceList());
return ns;
}
}
}
namespace WFCS
{
[DataContract]
public class IntContainer : IComparable
{
[DataMember]
public Int32 Value;
public IntContainer(int aInt32)
{
this.Value = aInt32;
}
public int CompareTo(object obj)
{
return this.Value.CompareTo(((IntContainer)obj).Value);
}
}
}
namespace WFCS
{
public class MotherActivity : Activity
{
[RequiredArgument]
public InArgument<IntContainer> IntToAdd { get; set; }
[RequiredArgument]
public InArgument<SortedList<IntContainer, SimpleData>> DataToProcess { get; set; }
[RequiredArgument]
public OutArgument<SortedList<IntContainer, SimpleData>> ProcessedData { get; set; }
private DelegateInArgument<SimpleData> simpleDataIterator;
private Variable<SimpleData> wfvar_tmpsimpledata;
private SimpleData native_tmpsimpledata;
protected override Func<Activity> Implementation
{
get
{
return () =>
{
Sequence seq = new Sequence
{
Variables =
{
},
Activities =
{
new WriteLine
{
Text = new InArgument<String>((env) => "I'm entering the mother activity processing nb = " + DataToProcess.Get(env).Count)
},
new Assign<SortedList<IntContainer, SimpleData>>
{
To = new CSharpReference<SortedList<IntContainer, SimpleData>>("ProcessedData"),
Value = new CSharpValue<SortedList<IntContainer, SimpleData>>("new SortedList<IntContainer, SimpleData>()"),
},
new ForEach<SimpleData>
{
Values = new InArgument<IEnumerable<SimpleData>>((env) => (IList<SimpleData>)DataToProcess.Get(env).Values),
Body = new ActivityAction<SimpleData>()
{
Argument = simpleDataIterator,
Handler = new Sequence()
{
Variables =
{
wfvar_tmpsimpledata
},
Activities =
{
new Assign<SimpleData>
{
To = new CSharpReference<SimpleData>("WFVAR_tmpsimpledata"),
Value = new InArgument<SimpleData>((env) => simpleDataIterator.Get(env))
},
new SimpleActivity
{
IntContainer = new CSharpValue<IntContainer>("new WFCS.IntContainer(IntToAdd.Value + WFVAR_tmpsimpledata.ID.Value);"),
StringContainer = new CSharpValue<StringContainer>("new WFCS.StringContainer(\"toto\");"),
Result = new CSharpReference<SimpleData>("WFVAR_tmpsimpledata")
},
new AddToCollection<KeyValuePair<IntContainer, SimpleData>>
{
Collection = new InArgument<ICollection<KeyValuePair<IntContainer,SimpleData>>>((env) => ProcessedData.Get(env)),
Item = new InArgument<KeyValuePair<IntContainer, SimpleData>>( (env) => (new KeyValuePair<IntContainer, SimpleData>(wfvar_tmpsimpledata.Get(env).ID,
wfvar_tmpsimpledata.Get(env))))
}
}
}
}
}
}
};
return seq;
};
}
set
{
base.Implementation = value;
}
}
public MotherActivity()
{
simpleDataIterator = new DelegateInArgument<SimpleData>();
native_tmpsimpledata = new SimpleData(0, "notset");
wfvar_tmpsimpledata = new Variable<SimpleData>("WFVAR_tmpsimpledata", ctx => native_tmpsimpledata);
}
}
}
namespace WFCS
{
public class PatriarchActivity : Activity
{
// remove this "fake" input
//[RequiredArgument]
//public InArgument<SortedList<IntContainer, SimpleData>> DataToProcess { get; set; }
[RequiredArgument]
public OutArgument<SortedList<IntContainer, SimpleData>> ProcessedData { get; set; }
IntContainer native_intcontainer;
Variable<IntContainer> wfvar_intcontainer;
SortedList<IntContainer, SimpleData> native_dataToProcess;
Variable<SortedList<IntContainer, SimpleData>> wfvar_dataToProcess;
protected override Func<Activity> Implementation
{
get
{
return () =>
{
Sequence seq = new Sequence
{
Variables =
{
wfvar_intcontainer, wfvar_dataToProcess
},
Activities =
{
new Assign<SortedList<IntContainer, SimpleData>>
{
To = new CSharpReference<SortedList<IntContainer, SimpleData>>("WFVAR_dataToProcess"),
Value = new CSharpValue<SortedList<IntContainer, SimpleData>>("new SortedList<IntContainer, SimpleData>()"),
},
new Assign<SortedList<IntContainer, SimpleData>>
{
To = new CSharpReference<SortedList<IntContainer, SimpleData>>("ProcessedData"),
Value = new CSharpValue<SortedList<IntContainer, SimpleData>>("new SortedList<IntContainer, SimpleData>()"),
},
new AddToCollection<KeyValuePair<IntContainer, SimpleData>>
{
Collection = wfvar_dataToProcess,
Item = new InArgument<KeyValuePair<IntContainer, SimpleData>>( (env) => (new KeyValuePair<IntContainer, SimpleData>(new IntContainer(1),
new SimpleData(1, "toto"))))
},
new AddToCollection<KeyValuePair<IntContainer, SimpleData>>
{
Collection = wfvar_dataToProcess,
Item = new InArgument<KeyValuePair<IntContainer, SimpleData>>( (env) => (new KeyValuePair<IntContainer, SimpleData>(new IntContainer(2),
new SimpleData(2, "titi"))))
},
new WriteLine
{
Text = new InArgument<String>((env) => "I'm in the patriarch activity processing nb = " + wfvar_dataToProcess.Get(env).Count)
},
new MotherActivity
{
IntToAdd = new CSharpValue<IntContainer>("WFVAR_intcontainer"),
DataToProcess = new CSharpValue<SortedList<IntContainer, SimpleData>>("WFVAR_dataToProcess"),
ProcessedData = new CSharpReference<SortedList<IntContainer,SimpleData>>("ProcessedData")
}
}
};
return seq;
};
}
set
{
base.Implementation = value;
}
}
public PatriarchActivity()
{
native_intcontainer = new IntContainer(42);
wfvar_intcontainer = new Variable<IntContainer>("WFVAR_intcontainer", ctx => native_intcontainer);
//native_dataToProcess = new SortedList<IntContainer, SimpleData>();
//wfvar_dataToProcess = new Variable<SortedList<IntContainer, SimpleData>>("WFVAR_dataToProcess", ctx => native_dataToProcess);
wfvar_dataToProcess = new Variable<SortedList<IntContainer, SimpleData>>("WFVAR_dataToProcess");
}
}
}
namespace WFCS
{
public class SimpleActivity : NativeActivity<SimpleData>
{
[RequiredArgument]
public InArgument<StringContainer> StringContainer { get; set; }
[RequiredArgument]
public InArgument<IntContainer> IntContainer { get; set; }
protected override void Execute(NativeActivityContext context)
{
this.Result.Set(context, new SimpleData(context.GetValue(IntContainer).Value,
context.GetValue(StringContainer).Value));
}
}
}
namespace WFCS
{
[DataContract]
public class SimpleData
{
[DataMember]
public IntContainer ID;
[DataMember]
public StringContainer Str;
public SimpleData(Int32 aInt32, String aString)
{
ID = new IntContainer(aInt32);
Str = new StringContainer(aString);
}
}
}
namespace WFCS
{
[DataContract]
public class StringContainer
{
[DataMember]
public String Value;
public StringContainer(string aString)
{
this.Value = aString;
}
}
}
和单元测试对应这三个活动:(需要Microsoft ..Activities.UnitTesting NuGet包)
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using WFCS;
using Microsoft.Activities.UnitTesting;
namespace WFCSTest
{
[TestClass]
public class SimpleActivityTest
{
[TestMethod]
public void TestSimpleActivity1()
{
SimpleActivity activity = ActivityCompiler.Instance.GetSimpleActivity();
WorkflowInvokerTest host = WorkflowInvokerTest.Create(activity);
host.InArguments.StringContainer = new StringContainer("Jesus");
host.InArguments.IntContainer = new IntContainer(42);
try
{
host.TestActivity();
SimpleData res = host.OutArguments.Result;
Assert.AreEqual(res.ID.Value, 42);
}
finally
{
host.Tracking.Trace();
}
}
}
}
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using WFCS;
using Microsoft.Activities.UnitTesting;
using System.Collections.Generic;
namespace WFCSTest
{
[TestClass]
public class MotherActivityTest
{
[TestMethod]
public void TestMotherActivity1()
{
SortedList<IntContainer, SimpleData> input = new SortedList<IntContainer, SimpleData>();
input.Add(new IntContainer(42), new SimpleData(42, "toto"));
input.Add(new IntContainer(84), new SimpleData(84, "titi"));
MotherActivity activity = ActivityCompiler.Instance.GetMotherActivity();
WorkflowInvokerTest host = WorkflowInvokerTest.Create(activity);
host.InArguments.IntToAdd = new IntContainer(21);
host.InArguments.DataToProcess = input;
try
{
host.TestActivity();
SortedList<IntContainer, SimpleData> res = host.OutArguments.ProcessedData;
Assert.AreEqual(res.Count, input.Count);
}
finally
{
host.Tracking.Trace();
}
}
}
}
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using WFCS;
using Microsoft.Activities.UnitTesting;
namespace WFCSTest
{
[TestClass]
public class PatriarchActivityTest
{
[TestMethod]
public void TestPatriarchActivity1()
{
PatriarchActivity activity = ActivityCompiler.Instance.GetPatriarchActivity();
WorkflowInvokerTest host = WorkflowInvokerTest.Create(activity);
//host.InArguments.IntToAdd = new IntContainer(21);
//host.InArguments.DataToProcess = new SortedList<IntContainer, SimpleData>();
//host.InArguments.ProcessedData = new SortedList<IntContainer, SimpleData>();
try
{
host.TestActivity();
SortedList<IntContainer, SimpleData> res = host.OutArguments.ProcessedData;
Assert.AreEqual(res.Count, 2);
}
finally
{
host.Tracking.Trace();
}
}
}
}