WF4 RC - 使用 ActivityXamlServices 从松散 Xaml 加载 WF 服务时无法创建未知类型

发布于 2024-08-22 10:50:56 字数 9705 浏览 3 评论 0原文

我正在尝试动态托管 WF4 (RC) 服务。我有一个包含两个项目的测试解决方案。第一个是声明性工作流服务库,其中包含一个根 Flowchart 活动和一个简单的自定义代码活动。工作流服务库不依赖于任何其他自定义程序集或引用。第二个是我的主机应用程序,在我的测试解决方案中它只是一个控制台应用程序。

在我的主机应用程序中,我尝试使用 ActivityXamlServices 将工作流服务的 Xaml 加载到活动中,然后使用 WorkflowServiceHost 使用该活动启动工作流实例。

当我尝试新建 WorkflowServiceHost 对象时,我收到此异常......

无法创建未知类型 '{clr-namespace:DeclarativeServiceLibrary1}CodeActivity1'。

如果我从流程图设计器中删除 CodeActivity1,一切都会正常运行。如果我从宿主项目添加对工作流服务项目的直接引用,然后使用 Flowchart 活动的实例而不是从 Xaml 创建的活动创建 WorkflowServiceHost,它也可以正常工作。

由于某种原因,动态加载时似乎不喜欢使用我的 CodeActivity。

有人知道为什么我无法动态创建工作流程服务吗?

我的代码如下...

DeclarativeServiceLibrary1.Activity1.xaml...

<Activity mc:Ignorable="sap" x:Class="DeclarativeServiceLibrary1.Activity1" sap:VirtualizedContainerService.HintSize="654,676" mva:VisualBasic.Settings="Assembly references and imported namespaces for internal implementation" xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities" xmlns:av="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:local="clr-namespace:DeclarativeServiceLibrary1" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mv="clr-namespace:Microsoft.VisualBasic;assembly=System" xmlns:mva="clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities" xmlns:p="http://schemas.microsoft.com/netfx/2009/xaml/servicemodel" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:s1="clr-namespace:System;assembly=System" xmlns:s2="clr-namespace:System;assembly=System.Xml" xmlns:s3="clr-namespace:System;assembly=System.Core" xmlns:sad="clr-namespace:System.Activities.Debugger;assembly=System.Activities" xmlns:sap="http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation" xmlns:scg="clr-namespace:System.Collections.Generic;assembly=System" xmlns:scg1="clr-namespace:System.Collections.Generic;assembly=System.ServiceModel" xmlns:scg2="clr-namespace:System.Collections.Generic;assembly=System.Core" xmlns:scg3="clr-namespace:System.Collections.Generic;assembly=mscorlib" xmlns:sd="clr-namespace:System.Data;assembly=System.Data" xmlns:sl="clr-namespace:System.Linq;assembly=System.Core" xmlns:st="clr-namespace:System.Text;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Flowchart sad:XamlDebuggerXmlReader.FileName="C:\dev\test\MyWorkflow\DeclarativeServiceLibrary1\Activity1.xaml" sap:VirtualizedContainerService.HintSize="614,636">
    <sap:WorkflowViewStateService.ViewState>
      <scg3:Dictionary x:TypeArguments="x:String, x:Object">
        <x:Boolean x:Key="IsExpanded">False</x:Boolean>
        <av:Point x:Key="ShapeLocation">270,2.5</av:Point>
        <av:Size x:Key="ShapeSize">60,75</av:Size>
        <av:PointCollection x:Key="ConnectorLocation">300,77.5 300,107.5 300,165</av:PointCollection>
      </scg3:Dictionary>
    </sap:WorkflowViewStateService.ViewState>
    <Flowchart.StartNode>
      <FlowStep x:Name="__ReferenceID0">
        <sap:WorkflowViewStateService.ViewState>
          <scg3:Dictionary x:TypeArguments="x:String, x:Object">
            <av:Point x:Key="ShapeLocation">172.5,165</av:Point>
            <av:Size x:Key="ShapeSize">255,90</av:Size>
            <av:PointCollection x:Key="ConnectorLocation">300,255 300,285 300,299.5</av:PointCollection>
          </scg3:Dictionary>
        </sap:WorkflowViewStateService.ViewState>
        <p:Receive CanCreateInstance="True" sap:VirtualizedContainerService.HintSize="255,90" OperationName="MyOperation" ServiceContractName="MyContractName" />
        <FlowStep.Next>
          <FlowStep x:Name="__ReferenceID1">
            <sap:WorkflowViewStateService.ViewState>
              <scg3:Dictionary x:TypeArguments="x:String, x:Object">
                <av:Point x:Key="ShapeLocation">194.5,299.5</av:Point>
                <av:Size x:Key="ShapeSize">211,61</av:Size>
                <av:PointCollection x:Key="ConnectorLocation">300,360.5 300,390.5 300,399</av:PointCollection>
              </scg3:Dictionary>
            </sap:WorkflowViewStateService.ViewState>
            <WriteLine sap:VirtualizedContainerService.HintSize="211,61" Text="Workflow started" />
            <FlowStep.Next>
              <FlowStep x:Name="__ReferenceID3">
                <sap:WorkflowViewStateService.ViewState>
                  <scg3:Dictionary x:TypeArguments="x:String, x:Object">
                    <av:Point x:Key="ShapeLocation">200,399</av:Point>
                    <av:Size x:Key="ShapeSize">200,22</av:Size>
                    <av:PointCollection x:Key="ConnectorLocation">300,421 300,451 300,479.5</av:PointCollection>
                  </scg3:Dictionary>
                </sap:WorkflowViewStateService.ViewState>
                <local:CodeActivity1 sap:VirtualizedContainerService.HintSize="200,22" />
                <FlowStep.Next>
                  <FlowStep x:Name="__ReferenceID2">
                    <sap:WorkflowViewStateService.ViewState>
                      <scg3:Dictionary x:TypeArguments="x:String, x:Object">
                        <av:Point x:Key="ShapeLocation">194.5,479.5</av:Point>
                        <av:Size x:Key="ShapeSize">211,61</av:Size>
                      </scg3:Dictionary>
                    </sap:WorkflowViewStateService.ViewState>
                    <WriteLine sap:VirtualizedContainerService.HintSize="211,61" Text="The code activity worked!" />
                  </FlowStep>
                </FlowStep.Next>
              </FlowStep>
            </FlowStep.Next>
          </FlowStep>
        </FlowStep.Next>
      </FlowStep>
    </Flowchart.StartNode>
    <x:Reference>__ReferenceID0</x:Reference>
    <x:Reference>__ReferenceID1</x:Reference>
    <x:Reference>__ReferenceID2</x:Reference>
    <x:Reference>__ReferenceID3</x:Reference>
  </Flowchart>
</Activity>

DeclarativeServiceLibrary1.CodeActivity1.cs ...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Activities;

namespace DeclarativeServiceLibrary1
{

    public sealed class CodeActivity1 : CodeActivity
    {
        // Define an activity input argument of type string
        //public InArgument<string> Text { get; set; }

        // If your activity returns a value, derive from CodeActivity<TResult>
        // and return the value from the Execute method.
        protected override void Execute(CodeActivityContext context)
        {
            // Obtain the runtime value of the Text input argument
            //string text = context.GetValue(this.Text);
        }
    }
}

DeclarativeServiceLibrary1.Web.Config ...

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
</configuration>

ConsoleApplication1.Program.cs ...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Activities;
using System.Activities.XamlIntegration;
using System.ServiceModel;
using System.ServiceModel.Activities;
using System.ServiceModel.Description;
using System.Xaml;
using System.Reflection;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {            
            string baseAddress = @"http://localhost:8081/MyContractName";

            string curDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            string wfDefPath =  Path.Combine(curDir, "Activity1.xaml");

            Activity workflowActivity = (Activity)ActivityXamlServices.Load(wfDefPath); 
            WorkflowService service = new WorkflowService { Body = workflowActivity }; 
            Uri serviceUri = new Uri(baseAddress, UriKind.Absolute); 
            WorkflowServiceHost host = new WorkflowServiceHost(service, new Uri[] { serviceUri }); 
            host.Open();

            //Display that we are listening on the console window
            Console.WriteLine("Workflow '{0}' is listening at '{1}'", host.Activity.DisplayName, baseAddress);
            Console.ReadLine();
        }
    }
}

我在声明中有一个构建后事件将 Assembly 和 Xaml 文件复制到主机控制台应用程序的 bin\debug\ 文件夹中的工作流服务库。

I am trying to host a WF4 (RC) Service dynamically. I have a test solution with two projects. The first is a declarative workflow service library with one root Flowchart activity in it, and a simple custom code activity. The workflow service library does not depend on any other custom assemblies or references. The second is my host app, which in my test solution is just a console application.

In my host app, I am attempting to the use ActivityXamlServices to load the Xaml for the workflow service into an activity, and then use the WorkflowServiceHost to fire up a workflow instance using that activity.

As soon as I try to new up the WorkflowServiceHost object, I get this exception...

Cannot create unknown type
'{clr-namespace:DeclarativeServiceLibrary1}CodeActivity1'.

If I remove CodeActivity1 from my Flowchart designer, everything runs fine. If I add a direct reference to the workflow service project from my host project and then create a WorkflowServiceHost using an instance of my Flowchart activity instead of the activity created from the Xaml, it also works fine.

It seems to not like using my CodeActivity for some reason when loaded dynamically.

Anyone have any ideas as to why I can't dynamically create my workflow service?

My code is as follows...

DeclarativeServiceLibrary1.Activity1.xaml...

<Activity mc:Ignorable="sap" x:Class="DeclarativeServiceLibrary1.Activity1" sap:VirtualizedContainerService.HintSize="654,676" mva:VisualBasic.Settings="Assembly references and imported namespaces for internal implementation" xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities" xmlns:av="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:local="clr-namespace:DeclarativeServiceLibrary1" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mv="clr-namespace:Microsoft.VisualBasic;assembly=System" xmlns:mva="clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities" xmlns:p="http://schemas.microsoft.com/netfx/2009/xaml/servicemodel" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:s1="clr-namespace:System;assembly=System" xmlns:s2="clr-namespace:System;assembly=System.Xml" xmlns:s3="clr-namespace:System;assembly=System.Core" xmlns:sad="clr-namespace:System.Activities.Debugger;assembly=System.Activities" xmlns:sap="http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation" xmlns:scg="clr-namespace:System.Collections.Generic;assembly=System" xmlns:scg1="clr-namespace:System.Collections.Generic;assembly=System.ServiceModel" xmlns:scg2="clr-namespace:System.Collections.Generic;assembly=System.Core" xmlns:scg3="clr-namespace:System.Collections.Generic;assembly=mscorlib" xmlns:sd="clr-namespace:System.Data;assembly=System.Data" xmlns:sl="clr-namespace:System.Linq;assembly=System.Core" xmlns:st="clr-namespace:System.Text;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Flowchart sad:XamlDebuggerXmlReader.FileName="C:\dev\test\MyWorkflow\DeclarativeServiceLibrary1\Activity1.xaml" sap:VirtualizedContainerService.HintSize="614,636">
    <sap:WorkflowViewStateService.ViewState>
      <scg3:Dictionary x:TypeArguments="x:String, x:Object">
        <x:Boolean x:Key="IsExpanded">False</x:Boolean>
        <av:Point x:Key="ShapeLocation">270,2.5</av:Point>
        <av:Size x:Key="ShapeSize">60,75</av:Size>
        <av:PointCollection x:Key="ConnectorLocation">300,77.5 300,107.5 300,165</av:PointCollection>
      </scg3:Dictionary>
    </sap:WorkflowViewStateService.ViewState>
    <Flowchart.StartNode>
      <FlowStep x:Name="__ReferenceID0">
        <sap:WorkflowViewStateService.ViewState>
          <scg3:Dictionary x:TypeArguments="x:String, x:Object">
            <av:Point x:Key="ShapeLocation">172.5,165</av:Point>
            <av:Size x:Key="ShapeSize">255,90</av:Size>
            <av:PointCollection x:Key="ConnectorLocation">300,255 300,285 300,299.5</av:PointCollection>
          </scg3:Dictionary>
        </sap:WorkflowViewStateService.ViewState>
        <p:Receive CanCreateInstance="True" sap:VirtualizedContainerService.HintSize="255,90" OperationName="MyOperation" ServiceContractName="MyContractName" />
        <FlowStep.Next>
          <FlowStep x:Name="__ReferenceID1">
            <sap:WorkflowViewStateService.ViewState>
              <scg3:Dictionary x:TypeArguments="x:String, x:Object">
                <av:Point x:Key="ShapeLocation">194.5,299.5</av:Point>
                <av:Size x:Key="ShapeSize">211,61</av:Size>
                <av:PointCollection x:Key="ConnectorLocation">300,360.5 300,390.5 300,399</av:PointCollection>
              </scg3:Dictionary>
            </sap:WorkflowViewStateService.ViewState>
            <WriteLine sap:VirtualizedContainerService.HintSize="211,61" Text="Workflow started" />
            <FlowStep.Next>
              <FlowStep x:Name="__ReferenceID3">
                <sap:WorkflowViewStateService.ViewState>
                  <scg3:Dictionary x:TypeArguments="x:String, x:Object">
                    <av:Point x:Key="ShapeLocation">200,399</av:Point>
                    <av:Size x:Key="ShapeSize">200,22</av:Size>
                    <av:PointCollection x:Key="ConnectorLocation">300,421 300,451 300,479.5</av:PointCollection>
                  </scg3:Dictionary>
                </sap:WorkflowViewStateService.ViewState>
                <local:CodeActivity1 sap:VirtualizedContainerService.HintSize="200,22" />
                <FlowStep.Next>
                  <FlowStep x:Name="__ReferenceID2">
                    <sap:WorkflowViewStateService.ViewState>
                      <scg3:Dictionary x:TypeArguments="x:String, x:Object">
                        <av:Point x:Key="ShapeLocation">194.5,479.5</av:Point>
                        <av:Size x:Key="ShapeSize">211,61</av:Size>
                      </scg3:Dictionary>
                    </sap:WorkflowViewStateService.ViewState>
                    <WriteLine sap:VirtualizedContainerService.HintSize="211,61" Text="The code activity worked!" />
                  </FlowStep>
                </FlowStep.Next>
              </FlowStep>
            </FlowStep.Next>
          </FlowStep>
        </FlowStep.Next>
      </FlowStep>
    </Flowchart.StartNode>
    <x:Reference>__ReferenceID0</x:Reference>
    <x:Reference>__ReferenceID1</x:Reference>
    <x:Reference>__ReferenceID2</x:Reference>
    <x:Reference>__ReferenceID3</x:Reference>
  </Flowchart>
</Activity>

DeclarativeServiceLibrary1.CodeActivity1.cs ...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Activities;

namespace DeclarativeServiceLibrary1
{

    public sealed class CodeActivity1 : CodeActivity
    {
        // Define an activity input argument of type string
        //public InArgument<string> Text { get; set; }

        // If your activity returns a value, derive from CodeActivity<TResult>
        // and return the value from the Execute method.
        protected override void Execute(CodeActivityContext context)
        {
            // Obtain the runtime value of the Text input argument
            //string text = context.GetValue(this.Text);
        }
    }
}

DeclarativeServiceLibrary1.Web.Config ...

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
</configuration>

ConsoleApplication1.Program.cs ...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Activities;
using System.Activities.XamlIntegration;
using System.ServiceModel;
using System.ServiceModel.Activities;
using System.ServiceModel.Description;
using System.Xaml;
using System.Reflection;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {            
            string baseAddress = @"http://localhost:8081/MyContractName";

            string curDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            string wfDefPath =  Path.Combine(curDir, "Activity1.xaml");

            Activity workflowActivity = (Activity)ActivityXamlServices.Load(wfDefPath); 
            WorkflowService service = new WorkflowService { Body = workflowActivity }; 
            Uri serviceUri = new Uri(baseAddress, UriKind.Absolute); 
            WorkflowServiceHost host = new WorkflowServiceHost(service, new Uri[] { serviceUri }); 
            host.Open();

            //Display that we are listening on the console window
            Console.WriteLine("Workflow '{0}' is listening at '{1}'", host.Activity.DisplayName, baseAddress);
            Console.ReadLine();
        }
    }
}

I have a post-build event in the delarative workflow service library that copies the Assembly and Xaml file into the bin\debug\ folder of the host console app.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

极致的悲 2024-08-29 10:50:56

简短的回答 - Xaml 加载无法推断本地(默认)程序集,因此您需要在 XamlReaderSettings.LocalAssembly 上指定它。

Short answer - Xaml load can't infer the local (default) assembly, so you need to specify it on XamlReaderSettings.LocalAssembly.

池予 2024-08-29 10:50:56

活动的开源代码。
将“xmlns:local=”clr-namespace:DeclarativeServiceLibrary1”更改为
xmlns:local =“clr命名空间:DeclarativeServiceLibrary1;程序集= DeclarativeServiceLibrary1”。

Open source code of the activity.
Change "xmlns:local="clr-namespace:DeclarativeServiceLibrary1" to
xmlns:local="clr-namespace:DeclarativeServiceLibrary1;assembly=DeclarativeServiceLibrary1".

赠佳期 2024-08-29 10:50:56

您直接反序列化 xaml 文件,但它引用了一个类型 (CodeActivity1),该类型被编译为 CLR 类型到 DeclarativeServiceLibrary1 程序集中。最明显的答案是 DeclarativeServiceLibrary1 程序集在运行时不可用于控制台应用程序。确保将此程序集复制到运行控制台应用程序的文件夹 (\bin\debug) 中,看看这是否会产生影响。

最重要的是,即使您直接读取 xaml 文件,它仍然需要访问它引用的任何类型。

You're deserializing the xaml file directly, but it is referencing a type (CodeActivity1) that is compiled as a CLR type into the DeclarativeServiceLibrary1 assembly. The most obvious answer is that the DeclarativeServiceLibrary1 assembly is not available to the console app at runtime. Make sure that this assembly is copied into the folder where you are running the console app (\bin\debug) and see if that makes a difference.

The bottom line is that even though you are reading the xaml file directly, it still needs access to any types that it references.

黑寡妇 2024-08-29 10:50:56

通过查看您的代码,我可以看出您应该加载 WorkflowService 而不是简单的活动。这里基本上有两个选项可供尝试:

选项 1:加载活动并将其托管在生成的工作流服务中。

您可以通过正常加载活动并使用以下代码片段将其放入工作流服务实例:

WorkflowService service = new WorkflowService();
service.Body = loadedActivity;

之后您可以将其托管在工作流服务主机内。

选项2:直接加载工作流服务

第二个选项与您现在的没有太大区别。但您需要使用 XamlServices 类来加载工作流服务,而不是使用 ActivityXamlServices 类。之后,需要使用您在示例中使用的设置启动工作流服务主机。

By looking at your code I can tell that you should have loaded a WorkflowService instead of a simple activity. There are basically two options to try here:

Option 1: Load the activity and host it inside a generated workflow service.

You can do this by loading the activity as normal and use the following snippet to make it into a workflow service instance:

WorkflowService service = new WorkflowService();
service.Body = loadedActivity;

After that you can host it inside the workflow service host.

Option 2: Load the workflow service directly

The second option is not much different from what you have now. But instead of using the ActivityXamlServices class you will need to use the XamlServices class to load the workflow service. After that it's a matter of firing up the workflow service host with the settings you used in your sample.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文