我正在尝试使用新的WF 4.5功能 - C#表达式编译动态活动。 它一直有效,直到我在表达式中添加一个外部类。
如果表达式包含基本对象,则表示已编译。 如果我添加对外部类的引用,则会生成错误“找不到类型或命名空间名称'xxxxx'(您是否缺少using指令或程序集引用?)”
那么,问题是我如何引用C#表达式的外部类?
P.S。它适用于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; }
}
}
答案 0 :(得分:9)
我遇到了一个与非动态活动相关的问题,现在已经检查了使其工作所需的内容:
添加对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);
为了得到这个答案,我需要在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);
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; }
}
}
答案 1 :(得分:0)
听起来你需要一个using语句来指定外部类所在的命名空间。
例如:
使用myNamespace;