You've already forked linux-packaging-mono
							
							
		
			
				
	
	
		
			343 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			343 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| #pragma warning disable 1634, 1691
 | |
| using System;
 | |
| using System.Diagnostics;
 | |
| using System.Collections;
 | |
| using System.Runtime.Serialization;
 | |
| using System.Runtime.Serialization.Formatters.Binary;
 | |
| using System.Collections.Generic;
 | |
| using System.Reflection;
 | |
| using System.Runtime.Remoting.Messaging;
 | |
| using System.Workflow.Runtime;
 | |
| using System.Security.Principal;
 | |
| using System.Threading;
 | |
| using System.Globalization;
 | |
| 
 | |
| namespace System.Workflow.Activities
 | |
| {
 | |
|     internal interface IMethodResponseMessage
 | |
|     {
 | |
|         void SendResponse(ICollection outArgs);
 | |
|         void SendException(Exception exception);
 | |
|         Exception Exception { get; }
 | |
|         ICollection OutArgs { get; }
 | |
|     }
 | |
| 
 | |
|     [Serializable]
 | |
|     internal sealed class MethodMessage : IMethodMessage, IMethodResponseMessage
 | |
|     {
 | |
|         [NonSerialized]
 | |
|         Type interfaceType;
 | |
|         [NonSerialized]
 | |
|         string methodName;
 | |
|         [NonSerialized]
 | |
|         object[] args;
 | |
|         [NonSerialized]
 | |
|         ManualResetEvent returnValueSignalEvent;
 | |
| 
 | |
|         object[] clonedArgs;
 | |
|         LogicalCallContext callContext;
 | |
| 
 | |
|         ICollection outArgs;
 | |
|         Exception exception;
 | |
| 
 | |
|         [NonSerialized]
 | |
|         bool responseSet = false;
 | |
| 
 | |
|         Guid callbackCookie;
 | |
| 
 | |
|         [NonSerialized]
 | |
|         MethodMessage previousMessage = null;
 | |
| 
 | |
|         static Dictionary<Guid, MethodMessage> staticMethodMessageMap = new Dictionary<Guid, MethodMessage>();
 | |
|         static Object syncRoot = new Object();
 | |
| 
 | |
|         internal MethodMessage(Type interfaceType, string methodName,
 | |
|                                object[] args, String identity) :
 | |
|             this(interfaceType, methodName, args, identity, false)
 | |
|         {
 | |
| 
 | |
|         }
 | |
| 
 | |
|         internal MethodMessage(Type interfaceType, string methodName,
 | |
|                                object[] args, String identity, bool responseRequired)
 | |
|         {
 | |
|             this.interfaceType = interfaceType;
 | |
|             this.methodName = methodName;
 | |
|             this.args = args;
 | |
|             callContext = GetLogicalCallContext();
 | |
| 
 | |
|             if (responseRequired)
 | |
|                 returnValueSignalEvent = new ManualResetEvent(false);
 | |
| 
 | |
|             PopulateIdentity(callContext, identity);
 | |
|             Clone();
 | |
|         }
 | |
| 
 | |
| 
 | |
| 
 | |
|         [OnSerializing]
 | |
|         void OnSerializing(StreamingContext context)
 | |
|         {
 | |
|             if (returnValueSignalEvent != null && !responseSet)
 | |
|             {
 | |
|                 callbackCookie = Guid.NewGuid();
 | |
| 
 | |
|                 lock (syncRoot)
 | |
|                 {
 | |
|                     staticMethodMessageMap.Add(callbackCookie, previousMessage ?? this);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         [OnDeserialized]
 | |
|         void OnDeserialized(StreamingContext context)
 | |
|         {
 | |
|             if (callbackCookie != Guid.Empty)
 | |
|             {
 | |
|                 lock (syncRoot)
 | |
|                 {
 | |
|                     if (staticMethodMessageMap.TryGetValue(callbackCookie, out previousMessage))
 | |
|                         staticMethodMessageMap.Remove(callbackCookie);
 | |
|                 }
 | |
| 
 | |
|                 if (previousMessage != null)
 | |
|                 {
 | |
|                     this.responseSet = previousMessage.responseSet;
 | |
|                     this.returnValueSignalEvent = previousMessage.returnValueSignalEvent;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             callbackCookie = Guid.Empty;
 | |
|         }
 | |
| 
 | |
|         string IMethodMessage.GetArgName(int index)
 | |
|         {
 | |
|             throw new NotImplementedException();
 | |
|         }
 | |
| 
 | |
|         object IMethodMessage.GetArg(int argNum)
 | |
|         {
 | |
|             return this.clonedArgs[argNum];
 | |
|         }
 | |
| 
 | |
|         string IMethodMessage.Uri
 | |
|         {
 | |
| #pragma warning disable 56503
 | |
|             // not implemented
 | |
|             get { throw new NotImplementedException(); }
 | |
| #pragma warning restore 56503
 | |
|         }
 | |
| 
 | |
|         string IMethodMessage.MethodName
 | |
|         {
 | |
|             get { return this.methodName; }
 | |
|         }
 | |
| 
 | |
|         string IMethodMessage.TypeName
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return (this.interfaceType.ToString());
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         object IMethodMessage.MethodSignature
 | |
|         {
 | |
| #pragma warning disable 56503
 | |
|             get { throw new NotImplementedException(); }
 | |
| #pragma warning restore 56503
 | |
|         }
 | |
| 
 | |
|         object[] IMethodMessage.Args
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return this.clonedArgs;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         object Clone()
 | |
|         {
 | |
|             object[] clones = new object[this.args.Length];
 | |
| 
 | |
|             for (int i = 0; i < this.args.Length; i++)
 | |
|             {
 | |
|                 clones[i] = Clone(this.args[i]);
 | |
|             }
 | |
|             this.clonedArgs = clones;
 | |
|             return clones;
 | |
|         }
 | |
| 
 | |
|         object Clone(object source)
 | |
|         {
 | |
|             if (source == null || source.GetType().IsValueType)
 | |
|                 return source;
 | |
| 
 | |
|             ICloneable clone = source as ICloneable;
 | |
|             if (clone != null)
 | |
|                 return clone.Clone();
 | |
| 
 | |
|             BinaryFormatter formatter = new BinaryFormatter();
 | |
|             System.IO.MemoryStream stream = new System.IO.MemoryStream(1024);
 | |
|             try
 | |
|             {
 | |
|                 formatter.Serialize(stream, source);
 | |
|             }
 | |
|             catch (SerializationException e)
 | |
|             {
 | |
|                 throw new InvalidOperationException(SR.GetString(SR.Error_EventArgumentSerializationException), e);
 | |
|             }
 | |
|             stream.Position = 0;
 | |
|             object cloned = formatter.Deserialize(stream);
 | |
|             return cloned;
 | |
|         }
 | |
| 
 | |
|         int IMethodMessage.ArgCount
 | |
|         {
 | |
|             get { return this.clonedArgs.Length; }
 | |
|         }
 | |
| 
 | |
|         bool IMethodMessage.HasVarArgs
 | |
|         {
 | |
| #pragma warning disable 56503
 | |
|             get { throw new NotImplementedException(); }
 | |
| #pragma warning restore 56503
 | |
|         }
 | |
| 
 | |
|         LogicalCallContext IMethodMessage.LogicalCallContext
 | |
|         {
 | |
|             get { return callContext; }
 | |
|         }
 | |
| 
 | |
|         MethodBase IMethodMessage.MethodBase
 | |
|         {
 | |
| #pragma warning disable 56503
 | |
|             get { throw new NotImplementedException(); }
 | |
| #pragma warning restore 56503
 | |
|         }
 | |
| 
 | |
|         IDictionary System.Runtime.Remoting.Messaging.IMessage.Properties
 | |
|         {
 | |
| #pragma warning disable 56503
 | |
|             get { throw new NotImplementedException(); }
 | |
| #pragma warning restore 56503
 | |
|         }
 | |
| 
 | |
|         void PopulateIdentity(LogicalCallContext callContext, String identity)
 | |
|         {
 | |
|             callContext.SetData(IdentityContextData.IdentityContext, new IdentityContextData(identity));
 | |
|         }
 | |
| 
 | |
|         static LogicalCallContext singletonCallContext;
 | |
|         static Object syncObject = new Object();
 | |
| 
 | |
|         static LogicalCallContext GetLogicalCallContext()
 | |
|         {
 | |
|             lock (syncObject)
 | |
|             {
 | |
|                 if (singletonCallContext == null)
 | |
|                 {
 | |
|                     CallContextProxy contextProxy = new CallContextProxy(typeof(IDisposable));
 | |
|                     IDisposable disposable = (IDisposable)contextProxy.GetTransparentProxy();
 | |
|                     disposable.Dispose();
 | |
|                     singletonCallContext = contextProxy.CallContext;
 | |
|                 }
 | |
|                 return singletonCallContext.Clone() as LogicalCallContext;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         #region IMethodResponseMessage implementation
 | |
| 
 | |
|         internal IMethodResponseMessage WaitForResponseMessage()
 | |
|         {
 | |
|             // todo wait for certain timeout
 | |
|             this.returnValueSignalEvent.WaitOne();
 | |
|             this.returnValueSignalEvent = null;
 | |
|             return this;
 | |
|         }
 | |
| 
 | |
|         public void SendResponse(ICollection outArgs)
 | |
|         {
 | |
|             if (this.returnValueSignalEvent == null)
 | |
|                 throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Error_WorkflowInstanceDehydratedBeforeSendingResponse)));
 | |
| 
 | |
|             if (!this.responseSet)
 | |
|             {
 | |
|                 this.OutArgs = outArgs;
 | |
|                 this.returnValueSignalEvent.Set();
 | |
|                 this.responseSet = true;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public void SendException(Exception exception)
 | |
|         {
 | |
|             if (this.returnValueSignalEvent == null)
 | |
|                 throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Error_WorkflowInstanceDehydratedBeforeSendingResponse)));
 | |
| 
 | |
|             if (!this.responseSet)
 | |
|             {
 | |
|                 this.Exception = exception;
 | |
|                 this.returnValueSignalEvent.Set();
 | |
|                 this.responseSet = true;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public Exception Exception
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return this.exception;
 | |
|             }
 | |
|             private set
 | |
|             {
 | |
|                 if (previousMessage != null)
 | |
|                     previousMessage.Exception = value;
 | |
| 
 | |
|                 this.exception = value;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public ICollection OutArgs
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return this.outArgs;
 | |
|             }
 | |
|             private set
 | |
|             {
 | |
|                 if (previousMessage != null)
 | |
|                     previousMessage.OutArgs = value;
 | |
| 
 | |
|                 this.outArgs = value;
 | |
|             }
 | |
|         }
 | |
|         #endregion
 | |
| 
 | |
|         private sealed class CallContextProxy : System.Runtime.Remoting.Proxies.RealProxy
 | |
|         {
 | |
|             LogicalCallContext callContext;
 | |
| 
 | |
|             internal LogicalCallContext CallContext
 | |
|             {
 | |
|                 get
 | |
|                 {
 | |
|                     return callContext;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             internal CallContextProxy(Type proxiedType)
 | |
|                 : base(proxiedType)
 | |
|             {
 | |
| 
 | |
|             }
 | |
| 
 | |
|             public override System.Runtime.Remoting.Messaging.IMessage Invoke(System.Runtime.Remoting.Messaging.IMessage msg)
 | |
|             {
 | |
|                 IMethodCallMessage methodCallMessage = msg as IMethodCallMessage;
 | |
|                 this.callContext = methodCallMessage.LogicalCallContext.Clone() as LogicalCallContext;
 | |
|                 return new ReturnMessage(null, null, 0, methodCallMessage.LogicalCallContext, methodCallMessage);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 |