object IOperationInvoker.Invoke(object instance, object[] inputs, out object[] outputs) { outputs = new object[0]; object retVal = null; Invoker invoker = null; // set incoming objects in the CallContext LCC.SetDataContract(OperationContext.Current.IncomingMessageHeaders, this._callContextActors); LogicalWorkflowContext lwc = LCC.LogicalWorkflowContext; // check the workflowId Guid workflowInstanceId = lwc.GetAndClearWorkflowId(); bool bGetWorkflowById = !workflowInstanceId.Equals(Guid.Empty); // options for workflow type if (this._workflowType == null) { string endpointUri = string.Concat(instance.GetType().FullName, ".", this._description.SyncMethod.Name); this._workflowType = RemotingServices.GetServerTypeForUri(endpointUri); } if (!bGetWorkflowById && this._workflowType == null) { // throw exception or perform some pre-processing retVal = this._innerOperationInvoker.Invoke(instance, inputs, out outputs); // done (no workflow invoked) return(retVal); } // create message operation MethodMessage message = new MethodMessage(this._description.SyncMethod, inputs, null); // workflow invoker options (statefull or stateless) if (bGetWorkflowById) { invoker = WorkflowInvoker.Create(workflowInstanceId); } else { invoker = WorkflowInvoker.Create(this._workflowType, lwc.WorkflowInitData); } // send message to the workflow queue invoker.SendMessage(message); // response if (!this._description.IsOneWay) { invoker.WaitForResponse(this.ResponseTime); retVal = invoker.GetResponse <object>(); } // done return(retVal); }
/// <summary> /// /// </summary> public void ProcessMessage(IMessage requestMessage, ITransportHeaders requestHeaders, Stream requestStream, out ITransportHeaders responseHeaders, out Stream responseStream) { object returnValue = null; responseHeaders = null; responseStream = new MemoryStream(); IMessage responseMsg = null; IMethodCallMessage mcm = requestMessage as IMethodCallMessage; BinaryFormatter bf = new BinaryFormatter(); try { if (_endpoint.StartsWith(WorkflowDefaults.WorkflowLocalhost)) { #region Invoke local Workflow LogicalWorkflowContext lwc = LCC.LogicalWorkflowContext; Guid workflowInstanceId = lwc.GetAndClearWorkflowId(); bool bGetWorkflowById = !workflowInstanceId.Equals(Guid.Empty); // create workflow Invoker invoker = null; if (bGetWorkflowById) { invoker = WorkflowInvoker.Create(workflowInstanceId); } else { string endpoint = _endpoint.Replace(WorkflowDefaults.WorkflowLocalhost, "").Trim('/'); Type workflowType = RemotingServices.GetServerTypeForUri(endpoint); invoker = WorkflowInvoker.Create(workflowType, lwc.WorkflowInitData); } // send remoting message invoker.SendMessage(mcm); // handle response if (RemotingServices.IsOneWay(mcm.MethodBase) == false) { invoker.WaitForResponse(_Sender.TimeOut); returnValue = invoker.GetResponse <object>(); } #endregion } else if (_endpoint.StartsWith(WorkflowDefaults.WorkflowByWCF)) { #region Invoke remote Workflow by WCF try { string endpoint = _endpoint.Replace(WorkflowDefaults.WorkflowByWCF, "").Trim('/'); using (ChannelFactory2 factory = new ChannelFactory2(Type.GetType(mcm.TypeName), endpoint)) { object tp = factory.CreateChannel(); using (OperationContextScope scope = new OperationContextScope(tp as IContextChannel)) { // CallContext over the loosely coupled contract (LogicalWorkflowContext and Unknown) object lwc = LCC.GetLogicalWorkflowContext; if (lwc != null) { MessageHeader header = MessageHeader.CreateHeader("LogicalWorkflowContext", "RKiss.WorkflowRemoting", lwc, false, "WorkflowRemoting"); OperationContext.Current.OutgoingMessageHeaders.Add(header); } if (!string.IsNullOrEmpty(Sender.CallContextActor)) { IDictionaryEnumerator enumerator = LCC.GetDataContract().GetEnumerator(); while (enumerator.MoveNext()) { // skip it if (enumerator.Value is LogicalWorkflowContext) { continue; } DataContractAttribute dca = enumerator.Key as DataContractAttribute; MessageHeader header = MessageHeader.CreateHeader(dca.Name, dca.Namespace, enumerator.Value, false, Sender.CallContextActor); OperationContext.Current.OutgoingMessageHeaders.Add(header); } } // action returnValue = factory.InvokeMethod(mcm.MethodName, mcm.Args); } factory.Close(); } } catch (TargetInvocationException ex) { throw ex.InnerException; } catch (Exception ex) { throw ex; } #endregion } else { throw new InvalidOperationException("No supported schema"); } // return value responseMsg = (IMessage) new ReturnMessage(returnValue, null, 0, null, mcm); } catch (System.ServiceModel.FaultException fe) { Exception ex = new Exception(fe.Message); ex.GetType().InvokeMember("_stackTraceString", BindingFlags.SetField | BindingFlags.NonPublic | BindingFlags.Instance, null, ex, new object[] { fe.ToString() }); responseMsg = new ReturnMessage(ex, mcm); } catch (Exception ex) { responseMsg = new ReturnMessage(ex, mcm); } finally { #region serialize IMessage response to return back bf.Serialize(responseStream, responseMsg); responseStream.Position = 0; responseHeaders = requestHeaders; #endregion } }
/// <summary> /// /// </summary> public ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream) { // scope state ServerProcessing servproc = ServerProcessing.Complete; responseMsg = null; responseHeaders = null; responseStream = new MemoryStream(); IMethodCallMessage mcm = null; BinaryFormatter bf = new BinaryFormatter(); try { //Are we in the business? if (_Next != null) { if (requestMsg == null && requestStream != null) { // we are supporting only binary formatter requestMsg = (IMessage)bf.Deserialize(requestStream); requestStream.Close(); } mcm = requestMsg as IMethodCallMessage; if (mcm == null) { throw new NullReferenceException("IMethodCallMessage after deserialization"); } // LogicalCallContext LCC.CopyFrom(mcm); LogicalWorkflowContext lwc = LCC.LogicalWorkflowContext; Guid workflowInstanceId = lwc.GetAndClearWorkflowId(); bool bGetWorkflowById = !workflowInstanceId.Equals(Guid.Empty); // create workflow Invoker invoker = null; if (bGetWorkflowById) { invoker = WorkflowInvoker.Create(workflowInstanceId); } else { string endpoint = mcm.Uri; if (string.IsNullOrEmpty(endpoint)) { endpoint = requestHeaders["__RequestUri"] as string; } if (string.IsNullOrEmpty(endpoint)) { throw new NullReferenceException("Internal error - missing endpoint"); } // create workflow instance Type workflowType = RemotingServices.GetServerTypeForUri(endpoint.TrimStart('/')); invoker = WorkflowInvoker.Create(workflowType, lwc.WorkflowInitData); } // send remoting message to the workflow invoker.SendMessage(mcm); // handle response if (!RemotingServices.IsOneWay(mcm.MethodBase)) { // wait for response invoker.WaitForResponse(_Provider.TimeOut); object response = invoker.GetResponse <object>(); // return message back to the caller (Note that this version is not allow to change a CallContext!!) responseMsg = (IMessage) new ReturnMessage(response, null, 0, null, mcm); } } else { throw new RemotingException("Internal error in the channel stack"); } } catch (Exception ex) { Trace.WriteLine(ex); responseMsg = (IMessage) new ReturnMessage(ex, mcm); } finally { responseHeaders = requestHeaders; if (responseMsg != null) { // serialize response to the wire transport bf.Serialize(responseStream, responseMsg); responseStream.Position = 0; } } return(servproc); }