返回首页

目录{A}微软的Windows Communication Foundation(WCF)中的Windows Workflow Foundation(WF)技术没有接收事件消息的自定义活动基于映射接口之间的WCF和工作流技术的合同事务支持声明方式编程没有要求建立一个本地服务空工作流本地服务相关事件NULL WCF服务在操作调用前/后处理能力工作与工作流本地服务并排(ExternalDataExchangeService)
微软的WF技术使人们有可能通过一个紧耦合的本地服务层接收外部(主机)事件。这一层简化的工作流程和主机应用程序的基础上的委托/事件模式之间的连接。所有这一切神奇的管道是隐蔽ExternalDataExchangeService类截获本地服务和特定的工作流队列生成一个事件消息。
为了接收由事件驱动的活动的事件消息,ExternalDataExchange接口契约必须声明与应用程序特定的事件处理程序。
事件委托有一个标准NET签名显示在下面的行。

 public void EventHandler(object sender, ExternalDataEventArgs eventArgs);

的EventArgs INSTANCEID,标识,应用程序特定的数据,等如工作流事件的兴趣
接口契约元数据是用来创造一个独特的工作流队列接口类型,事件的名称,并收集相关作为一个额外的选项模式的属性。请注意,工作流队列的消息是在主机应用程序可以谈工作流的唯一途径。
从连接点的看法,工作流事件接收器和WCF客户端的事件源(用户利益)。下面的图片显示了这个逻辑的模式:
{S0}
在事件源方面,我们可以创建多种模式(如Remoting中,WSE,WCF等)生成的事件消息,并将其发送到本地或远​​程工作流队列。
本文介绍如何使用WCF范式的基础上,每年年底端定义在不同的接口合约,可以实现连接。你会看到事件源可以是逻辑(声明的)与事件接收器元数据相连。
下面的图片显示了一个代表性的WCF事件源和WF事件接收器之间的松耦合连接:

注意,工作流方面并不需要有本地服务层,以产生一个事件消息。对于这个WCF / WF水暖,我们只需要元数据接口的合同和操作的一个通用的装饰当然,为了使所有法术的工作。
服务操作的合同可以被映射到具体的WF的接口合同中明确说明了使用WorkflowFireEventAttribute。此属性的背后,是一个管道代码生成一个事件消息发送到工作流队列。
使用WCF的连接提供一个事件消息的工作流事件接收器(如HandleExternalEventActivity),使建设与能力上的地址,绑定和合同为基础的WCF范例的应用程序模型。例如:交付事件消息netMsmgBinding约束力的异步和断开的方式或AJAX / JSON(Orcas的CTP版)带动了浏览器的事件消息交付启用一个连接的WebHttpBinding约束力。
让我们来看看详细的WCF / WF水暖是如何做工作流队列调度的事件消息。我将假定您熟悉这些技术。此外,我前面提到的,工作流方面不使用任何此管道的自定义活动,所以它是一个标准的工作流定义(顺序或状态机)使用HandleExternalEventActivity。因此,我将集中于管道的概念和实施。
松散耦合的WCF / WF工作流事件消息发送连接的概念是基于拦截服务经营合同,将其映射到具体ExternalDataExchange界面合同(见上面的图片)(WorkflowFireEventAttribute)。
WCF服务托管在同一个WorkflowRuntime的相同的AppDomain。基本上,我们需要创建一个空的服务,我们的WCF接口契约所得。下面是一个简单的空服务和接口契约的例子:{C}
在向上的AppDomain启动,WorkflowFireEventAttribute将插入一个WorkflowFireEventOperationInvoker的OperationInvoker拦截调用服务方法之前调用。下面的代码片段显示了一个方法,它是将派遣一个工作流的事件消息:
object IOperationInvoker.Invoke(object instance, object[] inputs, 

                            out object[] outputs)

{

  object retVal = null;

  outputs = new object[0];





  // validation for mandatory inputs

  if (inputs.Length < 2 || 

    !typeof(ExternalDataEventArgs).IsInstanceOfType(inputs[1]))

      throw new InvalidOperationException(string.Format(" ... ");



  // mandatory inputs

  object sender = inputs[0];

  ExternalDataEventArgs eventArgs = inputs[1] as ExternalDataEventArgs;



  if (Transaction.Current != null &&

    Transaction.Current.TransactionInformation.Status == 

                        TransactionStatus.Active)

  {

   WorkflowInstance workflowInstance = null;

   eventArgs.WaitForIdle = false;



   #region action - transactional delivery to the workflow queue

   using(TransactionScope ts = 

        new TransactionScope(TransactionScopeOption.RequiresNew))

   {

     // pre-processing

     if (this.Option == WorkflowFireEventOption.After)

     {

         retVal = this._innerOperationInvoker.Invoke(instance, inputs, 

                                out outputs);

     }



     // fire event

     workflowInstance =

      WorkflowHelper.DispatchEvent(this.EventType,this.EventName,

                        sender,eventArgs,true);



     // storing a workflow into the database

     workflowInstance.Unload();



     // post-process

     if (this.Option == WorkflowFireEventOption.Before)

     {

         retVal = this._innerOperationInvoker.Invoke(instance, inputs, 

                                out outputs);

     }



     // done

     ts.Complete();

   }



   try

   {

     // workaround to detect WorkflowStatus

     workflowInstance.Start();

   }

   catch (Exception ex)

   {

     // WorkflowStatus != Created (therefore we can go ahead and use it)

     Trace.WriteLine(ex.Message);

   }

   #endregion

  }

  else

  {

   #region action - non-transactional delivery to the workflow queue

   // pre-processing

   if (this.Option == WorkflowFireEventOption.After)

   {

     retVal = this._innerOperationInvoker.Invoke(instance, inputs, out outputs);

   }



   // dispatching event

   WorkflowHelper.DispatchEvent(this.EventType, this.EventName, 

                            sender, eventArgs);



   // post-processing

   if (this.Option == WorkflowFireEventOption.Before)

   {

     retVal = this._innerOperationInvoker.Invoke(instance, inputs, out outputs);

   }

   #endregion

 }

 return retVal;

}

基本上,该方法是分为3部分,如前处理,调度和后处理基础上的选项和事务上下文调用。选项​​可以为特定应用的逻辑,例如,创建工作流,填充的EventArgs属性,默认选项是"无。在呼叫其他分机使用强制性的参数,如输入[0]和投入[1]或输出背后的其他方法的参数。这些扩展应用程序的特定功能。在事务上下文的射击事件
事务的方式提供一个事件消息的工作流实例是有点不同的事务上下文驱动的其他资源。目前,我们没有一个工作流实例的事务的内存资源,因此ACID事务间接通过SqlWorkflowPersistenceService。这个概念是基于工作流实例发送的事件消息,在同步方式(WaitForIdle = FALSE)和脱水的交易范围内的工作流程,然后一直致力于在交易后,工作流返回到内存(补水) 。出于这个原因,我们要创建一个新的事务上下文来避免死锁。请注意,根据新的交易背景和他们的逻辑运行的预/后处理可以参加ACID事务。
让我们继续与调用dispatchEvent调用。此方法用于创建和启动工作流实例的基础上的eventArgs.InstanceId值,调用的辅助SendEventMessage方法来生成一个工作流程事件消息,并把它发送到实例队列。以下是dispatchEvent方法的代码片段:
public static WorkflowInstance DispatchEvent(Type interfaceType, 

    string eventName, object sender, ExternalDataEventArgs eventArgs)

{

  // input arguments validation

  if (interfaceType == null)

    throw new ArgumentNullException("interfaceType");

  if (string.IsNullOrEmpty(eventName))

    throw new ArgumentException("eventName");

  if (eventArgs == null)

    throw new ArgumentNullException("eventArgs");



  // Find the custom WCF Extension on the Service Host by it's type

  WFServiceHostExtension extension =

    OperationContext.Current.Host.Extensions.Find<WFServiceHostExtension>();



  // Get a reference to the WorkflowRuntime

  WorkflowRuntime workflowRuntime = extension.WorkflowRuntime;



  // get instance of the workflow

  WorkflowInstance instance = workflowRuntime.GetWorkflow(eventArgs.InstanceId);



  if (!bTransactional)

  {

    try

    {

      // workaround to detect WorkflowStatus

      instance.Start();

    }

    catch (Exception ex)

    {

      // WorkflowStatus != Created (therefore we can go ahead and use it)

      Trace.WriteLine(ex.Message);

    }

  }



  //WorkflowMessageEventHandler2 handler2 =

  //   new WorkflowMessageEventHandler2(interfaceType, eventName, instance);

  //handler2.EventHandler(sender, eventArgs);



  SendEventMessage(interfaceType, eventName, sender, eventArgs, instance);

  return instance;

}

请注意,这将是很好System.Workflow.Activities命名空间,这将大大简化了这一实施公共WorkflowMessageEventHandler类。我为此创建 - 看到helpers.cs文件,但它并不在交易范围内的工作(我会弄清楚这个问题,并更新)。现在,我们可以使用反射来调用内部类的公共方法,因为它是在下面的代码片段所示:
private static void SendEventMessage(Type interfaceType, string eventName,

  object sender, ExternalDataEventArgs eventArgs, WorkflowInstance instance)

{

 // get the type class

 Type type = 

    Type.GetType("System.Workflow.Activities.WorkflowMessageEventHandler, ...");



 // create instance

 object[] args1 =

  new object[3] {eventType, eventType.GetEvent(eventName), instance.WorkflowRuntime};

 object handler = Activator.CreateInstance(type, bindingAttr1, null, args1, cultureInfo);



 // invoke method

 object args2 = new object[2] { sender, eventArgs };

 type.InvokeMember("EventHandler", bindingAttr2, null, handler, args2);

}

WorkflowFireEventAttribute
这是一个管道类在经营合同中插入一个自定义调用执行调度事件消息从WCF的WF范例以松散耦合的方式。
WorkflowFireEventAttribute类可以发起以下属性:事件类型 - 类​​型ExternalDataExchange(强制性财产)归因于工作流界面EventName - 工作流事件的名称(默认事件的名称是经营合同的名称)WorkflowFireEventOption - 选项的操作调用前或后过程中的服务方法没有 - 没有服务方法调用(默认选项)前 - 工作流事件是发射前的服务方法调用烧制后的服务方法已被调用工作流事件后 -
使用上述物业在下面的例子所示,其中IFireEventTest接口映射到两个有相同的事件名工作流接口:
[ServiceBehavior]

public class ServiceTest1 : IFireEventTest

{

    [WorkflowFireEvent(EventType = typeof(IWorkflowSimpleEvents))]

    public void Approve(object sender, ExternalDataEventArgs e) { }



    [WorkflowFireEvent(EventType = typeof(IWorkflowEvents))]

    public void Reject(object sender, MyEventArgs e) { }



    [WorkflowFireEvent(EventName = "Reject", EventType = 

                    typeof(IMyWorkflowEvents))]

    public void MyReject(object sender, MyEventArgs e) { }

}


或在未来样本所示,我们可以如何处理调度范围内的操作方法或处理前发射工作流程事件的事件消息:
[ServiceBehavior]

public class ServiceTest2 : IFireEventTest

{

  public void Approve(object sender, ExternalDataEventArgs e, 

                        string workflowType)

  {

    // for test purpose

    MyObject mo = e.WorkItem as MyObject;

    Console.WriteLine("Operation Approve - {0}", mo.Name);



    // deliver message to the workflow instance

    WorkflowHelper.DispatchEvent(typeof(IWorkflowSimpleEvents), 

                        "Approve", sender, e);

  }



  [WorkflowFireEvent(Option = WorkflowFireEventOption.After,

    EventName = "Reject", EventType = typeof(IWorkflowEvents))]

  public void Reject(object sender, MyEventArgs e)

  {

    // for test purpose

    Console.WriteLine("Operation Reject - {0}", e.TaskName);

  }

}


正如我刚才所说,WCF连接使之间的任何事件源(​​客户端)和服务的结合使用。下面的代码片段显示了一个服务端点配置config文件的例子:
<service name="ServiceHost.ServiceTest1">

  <endpoint

    address="net.tcp://localhost:11111/Workflow"

    binding="netTcpBinding"

    contract="InterfaceContract.IFireEventTest"/>

</service>



<service name="ServiceHost.ServiceTest3">

  <endpoint

    address="net.msmq://localhost/private/rk.workflow_test"

    binding="netMsmqBinding"

    bindingConfiguration="PoisonBinding"

    contract="InterfaceContract.IFireEventTest"/>

</service>

相关事件
在使用相同的接口合约,事件(S)驱动多个工作流事件接收器情况下,必须与一个特定的参数值,在相同的工作流实例创建一个独特的工作流队列名称。在这篇文章中描述的解决方案支持此功能,它是完全透明的工作流事件接收器HandleExternalEventActivity(HEEA)的。此功能也WorkflowMessageEventHandler2类实施。
下面的代码片段显示了一个简单的事件拒绝相关的参数taskName上:
[ExternalDataExchange]

[CorrelationParameter("taskName")]

public interface IWorkflowEvents

{

    [CorrelationInitializer]

    void Initializer(string taskName);



    [CorrelationAlias("taskName", "TaskName")]

    event EventHandler<MyEventArgs> Reject;

}


相关事件需要有本地服务层执行CorrelationInitializer归因方法。此方法必须在特定的逻辑相关标记范围内调用本地服务HEEA事先告知相关值。
public class MyLocalService : IWorkflowEvents

{

    public void Initializer(string taskName)

    {

        Console.WriteLine("Initializer - {0}", taskName);

    }



    public event EventHandler<MyEventArgs> Reject;

}


请注意,在我们的松耦合连接,相关值可以被发送的事件源,也可以在WCF服务的操作方法前处理。附加的WorkflowRuntime
在WorkflowRuntime可以连接到WCF服务主机通过它的扩展。对于这种情况,我已经创建了两个构造一个WSServiceHostExtension类。第一个,将存储现有的WorkflowRuntime参考(例如:由Orcas中WorkflowServices创建),第二个会从配置文件中创建一个WorkflowRuntime的。
下面的代码片段显示了一个创建WorkflowRuntime的基础上的配置文件,并将其附加到WCF主机的例子:
using (System.ServiceModel.ServiceHost host =

   new System.ServiceModel.ServiceHost(typeof(ServiceTest3)))

{

 // Service extension for WF

 WFServiceHostExtension extension = 

    new WFServiceHostExtension("WorkflowRuntimeConfig");



 // Add the Extension to the ServiceHost collection

 host.Extensions.Add(extension);



 host.Open();



 Console.WriteLine("Press any key to stop server...");

 Console.ReadLine();



 host.Close();

}


工作流运行时配置的范例:

请注意,SqlWorkflowPersistenceService必须被包括在配置文件中。
FireWorkflowEvent解决方案分为两个文件夹,如WorkflowEventService - 托管的实施和WorkflowFireEventAttribute。此程序集必须包含托管WCF和WF的应用程序的AppDomain。测试的目的只是为了证明使用WorkflowFireEventAttribute其他文件夹。此文件夹包含几个项目 - 3的工作流程WorkflowLibrary(如ConsoleApplications生成一个事件,InterfaceContracts WCF和WF,WCF消息控制台上的简单的日志记录,ServiceHost的项目承载WCF服务和WorkflowRuntime的最后一个项目记录仪状态机,顺序和XOML激活)。
让我们开始测试。我认为您的环境netfx 3.0和SQLEXPRESS安装,包括一个工作流的东西。测试1。可拆卸事务事件
此测试演示通过事务性MSMQ事件源和事件接收器(WCF - 工作流程)之间的连接。从年底交付的事件消息,结束事务(可拆卸)的方式,使建设强大的事件驱动的体系结构。
以下是如何下探WCF和WF模型的主要步骤:第1步。工作流程
在这一步,我们需要创建一个EventHandler的方法(S)接口ExternalDataExchange合同。在我们的例子测试中,有简单的事件,批准工作流ExternalDataEventArgs。一旦我们有了这份合同,如HandleExternalEventActivity(HEEA)的事件接收器可以转让的。请注意,这是没有必要创建一个本地服务的实施。
下图显示了这些步骤 - 界面合同,HEEA物业和测试工作流程:
{S4}的
的所有工作流。下面的步骤是WCF只。第2步。 WCF服务
首先,我们需要创建一个服务(接口)合同消耗流事件(S)。下面的代码片段显示了一个简单的合同耗时两个事件 - 拒绝批准。在这个测试中,只批准活动将于火。
[ServiceContract]

public interface IFireEventTest

{

  [OperationContract(IsOneWay = true)]

  void Reject(object sender, MyEventArgs e);



  [OperationContract(IsOneWay = true)]

  void Approve(object sender, ExternalDataEventArgs e);

}


现在,我们可以创建一个服务和装饰为特定的事件与工作流程的整合。在这个测试中,我们要求事件后处理(触发事件前,看到选项)和IWorkflowSimpleEvents合同水暖操作调用。操作设置事务处理,自动犯。
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]

public class ServiceTest3 : IFireEventTest

{



 [WorkflowFireEvent(Option = WorkflowFireEventOption.Before,

   EventType = typeof(IWorkflowSimpleEvents))]

 [OperationBehavior(TransactionAutoComplete = 

            true, TransactionScopeRequired = true)]

 public void Approve(object sender, ExternalDataEventArgs e)

 {

   /*

   if(MessageBox.Show("Abort ...", "Approve", MessageBoxButtons.YesNo)==

                            DialogResult.Yes)

   {

      throw new Exception("Transaction has been aborted manually");

   }

   */

 }



 [WorkflowFireEvent(EventType = typeof(IWorkflowEvents))]

 public void Reject(object sender, MyEventArgs e) { }

}

主办这次在AppDomain中的服务之前,我们要创建一个服务的配置节。下面的代码片段显示ServiceHost.exe.config端点和NetMsmqBinding的文件的一部分。
<services>

  <service name="ServiceHost.ServiceTest3">

    <endpoint

      address="net.msmq://localhost/private/rk.workflow_test"

      binding="netMsmqBinding"

      bindingConfiguration="PoisonBinding"

      contract="InterfaceContract.IFireEventTest"/>

  </service>

</services>



<bindings>

  <netMsmqBinding>

    <binding name="PoisonBinding"

      receiveErrorHandling="Drop"

      receiveRetryCount="0"

      exactlyOnce="true"

      useSourceJournal="true"

      useActiveDirectory="false">

      <security mode="None" />

    </binding>

  </netMsmqBinding>

</bindings>


现在,我们可以承载在AppDomain中的上述服务 - ServiceHost的项目,Program.cs文件。之后,我们的工作流程已通过WCF服务公开获得核准事件消息。第3步。 WCF客户端
这一步,显示了一个例子,如何在客户端产生的交易方式批准事件。出于测试目的,workflow2.xoml是建立和坚持在射击事件之前。剩下的工作是直接的,如创建FireWorkflowEvent配置,应用程序的特定事件感兴趣的事件参数的通道和发送审批消息。请注意,将消息发送到MSMQ队列时,交易范围是致力。
using (TransactionScope ts = 

    new TransactionScope(TransactionScopeOption.RequiresNew))

{

  // unload workflow (for test purpose)

  using(XmlReader xmlReader=

    XmlReader.Create(@"..\..\..\WorkflowLibrary\Workflow2.xoml"))

  {

      wi = wr.CreateWorkflow(xmlReader);

  }

  wi.Unload();



  using (ChannelFactory<IFireEventTest> factory =

     new ChannelFactory<IFireEventTest>("FireWorkflowEvent"))

  {

    IFireEventTest channel = factory.CreateChannel();



    // eventArgs

    ExternalDataEventArgs eventArgs = 

        new ExternalDataEventArgs(wi.InstanceId);

    eventArgs.WaitForIdle = false;

    eventArgs.WorkItem = MyObject.Create(sender, ii);



    // fire workflow event

    channel.Approve(sender, eventArgs);



    // close this channel

    factory.Close();

  }



  ts.Complete();

}


现在,我们已经准备好作出实际的测试。第4步。运行测试
启动ConsoleApplication2方案。下面的屏幕片段展示了一个创建和装卸Workflow2过程中。使用包括记录器,在控制台屏幕上会显示一个事件消息发送到WCF服务的信封(和转发工作流程)。
{五}
启动ServiceHost的程序之前,消息可检查私人rk.workflow_test队列。我们没有约束力设置一个超时交付和接受服务的消息,因此,我们可以随时启动的服务。
下面的图片显示控制台屏幕片段ServiceHost的方案。我们可以看到在这台主机是多少端点,接收事件消息,以及如何此消息通过Workflow2。基于工作流定义,工作流会收到此消息后完成。
测试可重复另一个工作流实例ConsoleApplication2屏幕上按任意键。
{中六}
一件事。在第2步,我们都谈到了射击事件后处理。让我们的注释和运行服务的主机更多的时间。每个批准的事件调用将被打断的交易范围内的下列对话:
{七}
根据你的选择,我们可以模拟中止情景。请注意,消息是从MSMQ队列下降,但NetMsmqBinding的,如果你是在Vista上运行,可以使用毒药队列的重新配置。
此测试,让我们来看看的WorkflowFireEventAttribute另一个例子。测试2。触发相关事件
此测试演示一个相关的相关参数是taskName拒绝事件。每个工作流相关的范围有责任等待拒绝事件之前初始化参数。为此,工作流调用的CallExternalMethodActivity和相关参数的初始化值传递到主机应用程序,因此必须创建本地服务,并登记在WorkflowRuntime。
{S8}
{S9}
为了测试这种情况下,ServiceHost的程序必须ConsoleApplication1方案之前推出。请注意,本次测试使用应用程序的特定MyEventArgs从ExternalDataEventArgs衍生事件消息,因此,我们必须添加到LT这种类型; system.runtime.serializationgt;为配置文件(服务和客户端)的部分:
<system.runtime.serialization>

 <dataContractSerializer>

  <declaredTypes>

   <add type="System.Workflow.Activities.ExternalDataEventArgs, 

                        System.Workflow.Activities,

       Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">

     <knownType type ="InterfaceContract.MyObject, InterfaceContract"/>

   </add>

   <add type="InterfaceContract.MyEventArgs, InterfaceContract">

     <knownType type ="InterfaceContract.MyObject, InterfaceContract"/>

   </add>

  </declaredTypes>

 </dataContractSerializer>

</system.runtime.serialization>




让我们做的StateMachine工作流的测试。测试3。射击简单的状态机事件
下面的图片显示了一个国家的国家机器简单的例子,等待超时限制内批准事件。传入的​​批准事件将回收的状态,并重新引发超时限制。
{S10}
{S11}
{S12}
接口合同是非常简单的要求只有一个Null(无体)WCF服务。
为了测试这种情况下,ServiceHost的程序必须ConsoleApplication方案之前推出。
注意,测试ServiceHost的程序被配置为运行所有测试客户端控制台程序,因此它可以运行一个无限循环的测试。通用WCF服务
通用服务的目的是主机与一个典型的事件,如发件人和ExternalDataEventArgs参数签名简单事件的普遍服务。通过WorkItem的财产ExternalDataEventArgs对象工作流应用程序的特定对象可以被传递。
下面的代码片段显示了通用露出通过WCF工作流服务的完整的实施:
[ServiceContract]

public interface IFireWorkflowEvent

{

    [OperationContract(Action = "*", IsOneWay = true)]

    void FireWorkflowEvent(Message message);

}



[ServiceBehavior(IncludeExceptionDetailInFaults = true)]

public class WorkflowEventService : IFireWorkflowEvent

{

    public void FireWorkflowEvent(Message message)

    {

        WorkflowHelper.FireEvent(message);

    }

}


正如你可以看到,没有任何操作拦截器和映射接口合约WorkflowFireEventAttribute。基于隐式映射一个SOAP消息由事件和接口类型的名称定义的工作流界面合同的概念和这种解决方案的限制。经营合同的名称可以很容易地映射到工作流事件的名称。事件类型,如第二个映射要求并不简单。我决定现在使用WCF接口契约的命名空间。
OK,现在我们可以看看该WorkflowHelper.FireEvent如何将传入消息映射到工作流:
public static void FireEvent(Message message)

{

  System.Xml.XmlDictionaryReader reader = message.GetReaderAtBodyContents();



  // event contract

  Type interfaceType = Type.GetType(reader.NamespaceURI);

  string eventName = reader.Name;



  // body of the event message

  reader.ReadStartElement();

  string sender = reader.ReadElementContentAsString("sender", 

                        reader.NamespaceURI);

  DataContractSerializer xs =

            new DataContractSerializer(typeof(ExternalDataEventArgs), 

        "e", reader.NamespaceURI);

  ExternalDataEventArgs eventArgs = 

        (ExternalDataEventArgs)xs.ReadObject(reader);

  while (reader.NodeType != XmlNodeType.EndElement) { reader.Read(); }

  reader.ReadEndElement();



  // deliver message to the workflow queue

  DispatchEvent(interfaceType, eventName, sender, eventArgs);

}


FireEvent方法反序列化消息体获得前两个EventHandler的参数,如发件人和E.事件的合同,因为我上面提到的,是从方法的名称和命名空间。这些参数的dispatchEvent被称为派遣一个事件消息,以同样的方式,因为它已被前面所述的工作流队列。下面的代码片段显示了这个通用的WCF服务WCF接口契约的例子:
[ServiceContract(Namespace="InterfaceContract.IWorkflowSimpleEvents, 

                        InterfaceContract")]

public interface IFireEventTest2

{

    [OperationContract(IsOneWay = true)]

    void Approve(object sender, ExternalDataEventArgs e);

}


它是如何工作?
好了,之后一直在用的WorkflowRuntime的AppDomain中的WorkflowEventService托管,我们正在准备接收一个通过终点的事件消息。下面的配置片段显示这个通用的配置。当然,我们可以创建许多类型的绑定:
因此,客户端(如ConsoleApplication)将发送的事件消息基于WCF接口契约(如IFireEventTest2)以上的端点,转发到通用服务(行动="*")的运作FireWorkflowEvent。一旦我们有了一个方法的消息,我们的过程作为一个事件消息,否则将抛出一个异常。状态机中的相关事件
在多个事件驱动的活动(HEEA)时,等候在同一国家的同一事件的情况下,相关的功能可以帮助它。下图显示了相关参数,可以在初始化StateInitializationActivity。我并没有包括这个测试,因此这种情况下,尝试修改Workflow1与ConsoleApplication1程序对其进行测试。
{S13}
这篇文章描述了一个WCF / WF集成发射工作流事件。这个概念是基于WCF和WF界面合同之间的松耦合的连接。这是一个简单,透明的一体化,没有要求修改工作流和建设没有相关事件的一个自定义的本地服务。

回答

评论会员:sathyasakthivel 时间:2011/12/14
你会给予更多的屏幕截图,所以,这将是更容易理解{BR​​}
评论会员:JKJKJK 时间:2011/12/14
在我看来,这是旧的方式做的WCF WF相互作用。 。NET 3.5中,存在的ReceiveActivity它可以用来接收来自客户端的WCF调用。能否请您另一篇文章中描述该技术呢?

感谢
评论会员:罗马吻 时间:2011/12/14
阅读我的文章。
本文已发表和出版前。NetFX 3.5技术。

请看看以下的更先进的使用目前的MS技术的文章:





{A15}
感谢

罗马

微软的MVP - 连接系统开发
评论会员:陈智思Gressing 时间:2011/12/14

评论会员:sohair崎 时间:2011/12/14
请我开发一个基于Web的图书流通系统
我想用窗口的工作流程顺序,对检查出的书
部分子ID和书ID可以输入参数,我如何可以读取和更新的数据库,在Windows工作流
我应使用seqential工作流程库或Web servic

我使用Visual Studio 2005的
请我在哪里可以找到有关顺序工作流程和asp.net的信息,使工作流读取和更新图书流通数据库

感谢
评论会员:masaniparesh 时间:2011/12/14
您好,

能否请您帮助我以下的问题?

让我告诉你我的问题之后,你告诉我,我是否应该去通过WCF或不呢?

见我从Windows服务创建一个新的进程时,客户端应用程序调用它。我可以这样做成功,如果我的服务系统帐户下运行交互式其显示的所有窗口(如记事本,services.msc一切),但如果我让服务运行作为域\用户帐户,然后我可以运行的所有脚本,批处理progs的等,但不互动的过程。因此,在这种情况下,记事本窗口不出现,而客户端调用NOTEPAD.EXE即使在任务管理器,它是显示过程running.I发现,微软只提供系统帐户交互式窗口站,这是像这种情况发生的原因。所以基本上我的目的是在非系统帐户创建交互式窗口站。

我发现像GetWindowStation和SetWindowStation。你认为,这样我就可以实现这些功能这件事。目前我挖你有什么想法,这方面的所有这些functions.Ig的,那么它将会真的对我很有帮助。

感谢和问候,
Paresh


评论会员:eurocat13 时间:2011/12/14
允许服务与桌面交互

评论会员:gcsfred2001 时间:2011/12/14
什么的命名空间和WorkflowFireEvent大会?

GF
评论会员:罗马之吻 时间:2011/12/14
没有WorkflowFireEvent大会

感谢

罗马

微软MVP / Windows服务器系统 - 连接系统开发
评论会员:gcsfred2001 时间:2011/12/14
是什么,它​​在哪里定义?我找不到它的例子,它不能解决在Orcas的源代码。 - 感谢
评论会员:游客 时间:2011/12/14
安东尼中号Kancidrowski
WorkflowFireEvent是一个属性

参见

WorkflowEventService.cs

公共类的WorkflowFireEventAttribute:属性,IOperationBehavior 蚂蚁。
我辛苦,但软。
我有色,目前尚不清楚。
我圆润甜美。
我果冻,我是什么?缪斯进一步,我会回报! - 大卫Walliams(小英)