sse*_*hev 3 c# workflow-foundation
我正在尝试使用新的WF 4.5功能 - C#表达式编译动态活动.它一直有效,直到我在表达式中添加外部类.
如果表达式包含基本对象,则表示已编译.如果我添加对外部类的引用,则会生成错误"无法找到类型或命名空间名称'xxxxx'(您是否缺少using指令或程序集引用?)"
那么,问题是我如何引用C#表达式的外部类?
PS它适用于VisualBasic表达式类型
谢谢
//Compiled without errors
var errorCodeWorkflow = new DynamicActivity
{
Name = "DynamicActivity",
Implementation = () => new WriteLine
{
Text = new CSharpValue<String>
{
ExpressionText = "new Random().Next(1, 101).ToString()"
}
}
};
CompileExpressions(errorCodeWorkflow);
WorkflowInvoker.Invoke(errorCodeWorkflow);
//Error
using System;
using System.Activities;
using System.Activities.Expressions;
using System.Activities.Statements;
using System.Activities.XamlIntegration;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CSharp.Activities;
namespace CSharpExpression
{
class Program
{
static void Main()
{
var errorCodeWorkflow = new DynamicActivity
{
Name = "MyScenario.MyDynamicActivity3",
Properties =
{
new DynamicActivityProperty
{
Name = "Address",
Type = typeof(InArgument<MailAddress>),
},
},
Implementation = () => new WriteLine
{
Text = new CSharpValue<String>
{
ExpressionText = "\"MyDynamicActivity \" + Address.DisplayName"
}
}
};
CompileExpressions(errorCodeWorkflow);
WorkflowInvoker.Invoke(errorCodeWorkflow, new Dictionary<String, Object> { { "Address", new MailAddress { DisplayName = "TestDisplayName" } } });
}
static void CompileExpressions(DynamicActivity dynamicActivity)
{
var activityName = dynamicActivity.Name;
var activityType = activityName.Split('.').Last() + "_CompiledExpressionRoot";
var activityNamespace = string.Join(".", activityName.Split('.').Reverse().Skip(1).Reverse());
var settings = new TextExpressionCompilerSettings
{
Activity = dynamicActivity,
Language = "C#",
ActivityName = activityType,
ActivityNamespace = activityNamespace,
RootNamespace = "CSharpExpression",
GenerateAsPartialClass = false,
AlwaysGenerateSource = true,
ForImplementation = true
};
var results = new TextExpressionCompiler(settings).Compile();
if (results.HasErrors)
{
throw new Exception("Compilation failed.");
}
var compiledExpressionRoot = Activator.CreateInstance(results.ResultType, new object[] { dynamicActivity }) as ICompiledExpressionRoot;
CompiledExpressionInvoker.SetCompiledExpressionRootForImplementation(dynamicActivity, compiledExpressionRoot);
}
}
public class MailAddress
{
public String Address { get; set; }
public String DisplayName { get; set; }
}
}
Run Code Online (Sandbox Code Playgroud)
我遇到了一个与非动态活动相关的相同问题,现在已经检查了使其工作所需的内容:
添加引用 System.Xaml
移动MailAddress到其他名称空间.
Dynamic Activity在您的课程来源中添加一些信息:
var impl = new AttachableMemberIdentifier(typeof(TextExpression), "NamespacesForImplementation");
var namespaces = new List<string> { typeof(MailAddress).Namespace };
TextExpression.SetReferencesForImplementation(dynamicActivity, new AssemblyReference { Assembly = typeof(MailAddress).Assembly });
AttachablePropertyServices.SetProperty(dynamicActivity, impl, namespaces);
Run Code Online (Sandbox Code Playgroud)
为了得到这个答案,我需要在TextExpressionCompiler源头挖掘,以便可能有更优雅的东西.
如果您不使用动态活动,则调用CompileExpressions将按此处所述进行更改:http://msdn.microsoft.com/en-us/library/jj591618.aspx.
通过删除"ForImplementation"部分,可以修改向活动添加信息:
var impl = new AttachableMemberIdentifier(typeof(TextExpression), "Namespaces");
var namespaces = new List<string> { typeof(MailAddress).Namespace };
TextExpression.SetReferences(nonDynamicActivity, new AssemblyReference { Assembly = typeof(MailAddress).Assembly });
AttachablePropertyServices.SetProperty(nonDynamicActivity, impl, namespaces);
Run Code Online (Sandbox Code Playgroud)
using System;
using System.Activities;
using System.Activities.Expressions;
using System.Activities.Statements;
using System.Activities.XamlIntegration;
using System.Collections.Generic;
using System.Linq;
using System.Xaml;
using ExternalNamespace;
using Microsoft.CSharp.Activities;
namespace CSharpExpression
{
class Program
{
static void Main()
{
var errorCodeWorkflow = new DynamicActivity
{
Name = "MyScenario.MyDynamicActivity3",
Properties =
{
new DynamicActivityProperty
{
Name = "Address",
Type = typeof(InArgument<MailAddress>),
},
},
Implementation = () => new WriteLine
{
Text = new CSharpValue<String>
{
ExpressionText = "\"MyDynamicActivity \" + Address.DisplayName"
}
}
};
var impl = new AttachableMemberIdentifier(typeof(TextExpression), "NamespacesForImplementation");
var namespaces = new List<string> { typeof(MailAddress).Namespace };
TextExpression.SetReferencesForImplementation(errorCodeWorkflow, new AssemblyReference { Assembly = typeof(MailAddress).Assembly });
AttachablePropertyServices.SetProperty(errorCodeWorkflow, impl, namespaces);
CompileExpressions(errorCodeWorkflow);
WorkflowInvoker.Invoke(errorCodeWorkflow, new Dictionary<String, Object> { { "Address", new MailAddress { DisplayName = "TestDisplayName" } } });
}
static void CompileExpressions(DynamicActivity dynamicActivity)
{
var activityName = dynamicActivity.Name;
var activityType = activityName.Split('.').Last() + "_CompiledExpressionRoot";
var activityNamespace = string.Join(".", activityName.Split('.').Reverse().Skip(1).Reverse());
var settings = new TextExpressionCompilerSettings
{
Activity = dynamicActivity,
Language = "C#",
ActivityName = activityType,
ActivityNamespace = activityNamespace,
RootNamespace = "CSharpExpression",
GenerateAsPartialClass = false,
AlwaysGenerateSource = true,
ForImplementation = true
};
var results = new TextExpressionCompiler(settings).Compile();
if (results.HasErrors)
{
throw new Exception("Compilation failed.");
}
var compiledExpressionRoot = Activator.CreateInstance(results.ResultType, new object[] { dynamicActivity }) as ICompiledExpressionRoot;
CompiledExpressionInvoker.SetCompiledExpressionRootForImplementation(dynamicActivity, compiledExpressionRoot);
}
}
}
namespace ExternalNamespace
{
public class MailAddress
{
public String Address { get; set; }
public String DisplayName { get; set; }
}
}
Run Code Online (Sandbox Code Playgroud)