You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@@ -0,0 +1,463 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
#region Using directives
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Workflow.ComponentModel;
|
||||
using System.Runtime.Remoting;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
using System.Workflow.Runtime;
|
||||
using System.Xml;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace System.Workflow.Activities
|
||||
{
|
||||
internal static class CorrelationResolver
|
||||
{
|
||||
static Dictionary<Type, CorrelationMethodResolver> cachedTypeResolver = new Dictionary<Type, CorrelationMethodResolver>();
|
||||
static object mutex = new object();
|
||||
|
||||
internal static bool IsInitializingMember(Type interfaceType, string memberName, object[] methodArgs)
|
||||
{
|
||||
if (interfaceType == null)
|
||||
throw new ArgumentNullException("interfaceType");
|
||||
if (memberName == null)
|
||||
throw new ArgumentNullException("memberName");
|
||||
if (memberName.Length == 0)
|
||||
throw new ArgumentException(SR.GetString(SR.Error_EventNameMissing));
|
||||
|
||||
ICorrelationProvider correlationProvider = CorrelationResolver.GetCorrelationProvider(interfaceType);
|
||||
return correlationProvider.IsInitializingMember(interfaceType, memberName, methodArgs);
|
||||
}
|
||||
|
||||
internal static ICollection<CorrelationProperty> ResolveCorrelationValues(Type interfaceType, string eventName, object[] eventArgs, bool provideInitializerTokens)
|
||||
{
|
||||
if (interfaceType == null)
|
||||
throw new ArgumentNullException("interfaceType");
|
||||
if (eventName == null)
|
||||
throw new ArgumentNullException("eventName");
|
||||
if (eventName.Length == 0)
|
||||
throw new ArgumentException(SR.GetString(SR.Error_EventNameMissing));
|
||||
|
||||
ICorrelationProvider correlationProvider = CorrelationResolver.GetCorrelationProvider(interfaceType);
|
||||
return correlationProvider.ResolveCorrelationPropertyValues(interfaceType, eventName, eventArgs, provideInitializerTokens);
|
||||
}
|
||||
|
||||
internal static ICorrelationProvider GetCorrelationProvider(Type interfaceType)
|
||||
{
|
||||
CorrelationMethodResolver resolver = GetResolver(interfaceType);
|
||||
return resolver.CorrelationProvider;
|
||||
}
|
||||
|
||||
private static CorrelationMethodResolver GetResolver(Type interfaceType)
|
||||
{
|
||||
CorrelationMethodResolver resolver = null;
|
||||
cachedTypeResolver.TryGetValue(interfaceType, out resolver);
|
||||
if (resolver == null)
|
||||
{
|
||||
lock (mutex)
|
||||
{
|
||||
cachedTypeResolver.TryGetValue(interfaceType, out resolver);
|
||||
if (resolver == null)
|
||||
{
|
||||
resolver = new CorrelationMethodResolver(interfaceType);
|
||||
cachedTypeResolver.Add(interfaceType, resolver);
|
||||
}
|
||||
}
|
||||
}
|
||||
return resolver;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class CorrelationMethodResolver
|
||||
{
|
||||
Type interfaceType;
|
||||
|
||||
// a correlation provider for each interface type
|
||||
ICorrelationProvider correlationProvider;
|
||||
object corrProviderSync = new object();
|
||||
|
||||
internal CorrelationMethodResolver(Type interfaceType)
|
||||
{
|
||||
this.interfaceType = interfaceType;
|
||||
}
|
||||
|
||||
internal ICorrelationProvider CorrelationProvider
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.correlationProvider == null)
|
||||
{
|
||||
lock (this.corrProviderSync)
|
||||
{
|
||||
if (this.correlationProvider == null)
|
||||
{
|
||||
ICorrelationProvider provider = null;
|
||||
object[] corrProviderAttribs = this.interfaceType.GetCustomAttributes(typeof(CorrelationProviderAttribute), true);
|
||||
if (corrProviderAttribs.Length == 0)
|
||||
{
|
||||
corrProviderAttribs = this.interfaceType.GetCustomAttributes(typeof(ExternalDataExchangeAttribute), true);
|
||||
object[] corrParameterAttribs = this.interfaceType.GetCustomAttributes(typeof(CorrelationParameterAttribute), true);
|
||||
if (corrProviderAttribs.Length != 0 && corrParameterAttribs.Length != 0)
|
||||
{
|
||||
// no provider specified but it is a data exchange correlation service
|
||||
// hence use our default correlation
|
||||
provider = new DefaultCorrelationProvider(this.interfaceType);
|
||||
}
|
||||
else
|
||||
{
|
||||
// opaque interface with no correlation
|
||||
provider = new NonCorrelatedProvider();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CorrelationProviderAttribute cpattrib = corrProviderAttribs[0] as CorrelationProviderAttribute;
|
||||
Type providerType = cpattrib.CorrelationProviderType;
|
||||
provider = Activator.CreateInstance(providerType) as ICorrelationProvider;
|
||||
}
|
||||
|
||||
System.Threading.Thread.MemoryBarrier();
|
||||
this.correlationProvider = provider;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this.correlationProvider;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class CorrelationPropertyValue
|
||||
{
|
||||
string name;
|
||||
string locationPath;
|
||||
int signaturePosition;
|
||||
|
||||
internal CorrelationPropertyValue(string name, string locationPath, int signaturePosition)
|
||||
{
|
||||
this.name = name;
|
||||
this.locationPath = locationPath;
|
||||
this.signaturePosition = signaturePosition;
|
||||
}
|
||||
|
||||
internal object GetValue(object[] args)
|
||||
{
|
||||
if (args.Length <= this.signaturePosition)
|
||||
throw new ArgumentOutOfRangeException("args");
|
||||
|
||||
object arg = args[this.signaturePosition];
|
||||
if (arg == null)
|
||||
return arg;
|
||||
Type type = arg.GetType();
|
||||
object val = arg;
|
||||
if (this.locationPath.Length != 0)
|
||||
{
|
||||
string[] split = locationPath.Split(new Char[] { '.' });
|
||||
for (int i = 1; i < split.Length; i++)
|
||||
{
|
||||
string s = split[i];
|
||||
if (null == arg)
|
||||
break;
|
||||
val = type.InvokeMember(s, BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetField | BindingFlags.GetProperty, null, arg, null, null);
|
||||
|
||||
MemberInfo[] mInfos = type.GetMember(s, BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetField | BindingFlags.GetProperty);
|
||||
|
||||
type = GetMemberType(mInfos[0]);
|
||||
arg = val;
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
internal string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
|
||||
private Type GetMemberType(MemberInfo mInfo)
|
||||
{
|
||||
Type type = null;
|
||||
switch (mInfo.MemberType)
|
||||
{
|
||||
case MemberTypes.Field:
|
||||
type = ((FieldInfo)mInfo).FieldType;
|
||||
break;
|
||||
|
||||
case MemberTypes.Property:
|
||||
type = ((PropertyInfo)mInfo).PropertyType;
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug.Assert(false, "locationPath points to something other than a Field/Property");
|
||||
return null;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class DefaultCorrelationProvider : ICorrelationProvider
|
||||
{
|
||||
Type interfaceType;
|
||||
|
||||
// map of method name to correlation properties
|
||||
Dictionary<string, CorrelationPropertyValue[]> cachedCorrelationProperties;
|
||||
object cachedCorrelationPropertiesSync = new object();
|
||||
|
||||
// cached initializers
|
||||
// map operation to bool flag to indicate events
|
||||
Dictionary<string, bool> initializerCorrelationPropertys = null;
|
||||
object initializerCorrelationPropertysSync = new object();
|
||||
|
||||
internal DefaultCorrelationProvider(Type interfaceType)
|
||||
{
|
||||
this.cachedCorrelationProperties = new Dictionary<string, CorrelationPropertyValue[]>();
|
||||
this.interfaceType = interfaceType;
|
||||
}
|
||||
|
||||
ICollection<CorrelationProperty> ICorrelationProvider.ResolveCorrelationPropertyValues(Type interfaceType, string methodName, object[] methodArgs, bool provideInitializerTokens)
|
||||
{
|
||||
CorrelationPropertyValue[] correlationProperties = null;
|
||||
|
||||
if (methodArgs == null || provideInitializerTokens)
|
||||
{
|
||||
return null; // no initializer specific token to return
|
||||
}
|
||||
|
||||
this.cachedCorrelationProperties.TryGetValue(methodName, out correlationProperties);
|
||||
if (correlationProperties == null)
|
||||
{
|
||||
lock (this.cachedCorrelationPropertiesSync)
|
||||
{
|
||||
this.cachedCorrelationProperties.TryGetValue(methodName, out correlationProperties);
|
||||
if (correlationProperties == null)
|
||||
{
|
||||
correlationProperties = GetCorrelationProperties(interfaceType, methodName);
|
||||
this.cachedCorrelationProperties.Add(methodName, correlationProperties);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<CorrelationProperty> predicates = new List<CorrelationProperty>();
|
||||
for (int i = 0; i < correlationProperties.Length; i++)
|
||||
{
|
||||
predicates.Add(new CorrelationProperty(correlationProperties[i].Name, correlationProperties[i].GetValue(methodArgs)));
|
||||
}
|
||||
|
||||
return predicates;
|
||||
}
|
||||
|
||||
private Dictionary<string, bool> InitializerCorrelationPropertys
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.initializerCorrelationPropertys == null)
|
||||
{
|
||||
lock (this.initializerCorrelationPropertysSync)
|
||||
{
|
||||
if (this.initializerCorrelationPropertys == null)
|
||||
{
|
||||
Dictionary<string, bool> members = new Dictionary<string, bool>();
|
||||
// note this is separated out since we may need to distinguish between events & methods
|
||||
foreach (EventInfo member in this.interfaceType.GetEvents())
|
||||
{
|
||||
if ((member.GetCustomAttributes(typeof(CorrelationInitializerAttribute), true)).Length > 0)
|
||||
{
|
||||
members.Add(member.Name, true);
|
||||
}
|
||||
}
|
||||
foreach (MethodInfo member in this.interfaceType.GetMethods())
|
||||
{
|
||||
if ((member.GetCustomAttributes(typeof(CorrelationInitializerAttribute), true)).Length > 0)
|
||||
{
|
||||
members.Add(member.Name, false);
|
||||
}
|
||||
}
|
||||
|
||||
this.initializerCorrelationPropertys = members;
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.initializerCorrelationPropertys;
|
||||
}
|
||||
}
|
||||
|
||||
bool ICorrelationProvider.IsInitializingMember(Type interfaceType, string memberName, object[] methodArgs)
|
||||
{
|
||||
return InitializerCorrelationPropertys.ContainsKey(memberName);
|
||||
}
|
||||
|
||||
private CorrelationPropertyValue[] GetCorrelationProperties(Type interfaceType, string methodName)
|
||||
{
|
||||
CorrelationPropertyValue[] correlationProperties = null;
|
||||
|
||||
if (interfaceType.GetCustomAttributes(typeof(ExternalDataExchangeAttribute), true).Length == 0)
|
||||
throw new InvalidOperationException(SR.GetString(SR.Error_ExternalDataExchangeException, interfaceType.AssemblyQualifiedName));
|
||||
|
||||
List<Object> correlationParamAttributes = new List<Object>();
|
||||
correlationParamAttributes.AddRange(GetCorrelationParameterAttributes(interfaceType));
|
||||
|
||||
if (correlationParamAttributes.Count == 0)
|
||||
throw new InvalidOperationException(SR.GetString(SR.Error_CorrelationParameterException, interfaceType.AssemblyQualifiedName));
|
||||
|
||||
correlationProperties = new CorrelationPropertyValue[correlationParamAttributes.Count];
|
||||
|
||||
Dictionary<String, CorrelationAliasAttribute> corrAliases = null;
|
||||
MethodInfo methodInfo = null;
|
||||
|
||||
GetMethodInfo(interfaceType, methodName, out methodInfo, out corrAliases);
|
||||
|
||||
if (methodInfo == null)
|
||||
{
|
||||
throw new MissingMethodException(interfaceType.AssemblyQualifiedName, methodName);
|
||||
}
|
||||
|
||||
ParameterInfo[] parameters = methodInfo.GetParameters();
|
||||
|
||||
int i = 0;
|
||||
foreach (CorrelationParameterAttribute paramAttribute in correlationParamAttributes)
|
||||
{
|
||||
String location = paramAttribute.Name;
|
||||
CorrelationAliasAttribute aliasAttribute = GetMatchingCorrelationAlias(paramAttribute, corrAliases, correlationParamAttributes.Count == 1);
|
||||
|
||||
if (aliasAttribute != null)
|
||||
location = aliasAttribute.Path;
|
||||
|
||||
CorrelationPropertyValue value = GetCorrelationProperty(parameters, paramAttribute.Name, location);
|
||||
if (value == null)
|
||||
throw new InvalidOperationException(SR.GetString(SR.Error_CorrelationParameterException, interfaceType.AssemblyQualifiedName, paramAttribute.Name, methodName));
|
||||
|
||||
correlationProperties[i++] = value;
|
||||
}
|
||||
return correlationProperties;
|
||||
}
|
||||
|
||||
private CorrelationAliasAttribute GetMatchingCorrelationAlias(CorrelationParameterAttribute paramAttribute, Dictionary<String, CorrelationAliasAttribute> correlationAliases, bool defaultParameter)
|
||||
{
|
||||
CorrelationAliasAttribute corrAlias = null;
|
||||
|
||||
if (correlationAliases == null) return null;
|
||||
|
||||
if (defaultParameter)
|
||||
{
|
||||
if (correlationAliases.TryGetValue("", out corrAlias))
|
||||
{
|
||||
return corrAlias;
|
||||
}
|
||||
}
|
||||
|
||||
correlationAliases.TryGetValue(paramAttribute.Name, out corrAlias);
|
||||
return corrAlias;
|
||||
}
|
||||
|
||||
private CorrelationPropertyValue GetCorrelationProperty(ParameterInfo[] parameters, String propertyName, String location)
|
||||
{
|
||||
string[] split = location.Split(new Char[] { '.' });
|
||||
|
||||
if (split.Length == 1 && parameters.Length == 2)
|
||||
{
|
||||
if (typeof(ExternalDataEventArgs).IsAssignableFrom(parameters[1].ParameterType))
|
||||
{
|
||||
string aliasedLocation = "e." + location;
|
||||
return GetCorrelationProperty(parameters, propertyName, "e", aliasedLocation);
|
||||
}
|
||||
|
||||
}
|
||||
string parameterName = split[0];
|
||||
|
||||
return GetCorrelationProperty(parameters, propertyName, parameterName, location);
|
||||
}
|
||||
|
||||
private void GetMethodInfo(Type interfaceType, string methodName, out MethodInfo methodInfo, out Dictionary<String, CorrelationAliasAttribute> correlationAliases)
|
||||
{
|
||||
correlationAliases = new Dictionary<String, CorrelationAliasAttribute>();
|
||||
Object[] customAttrs = null;
|
||||
methodInfo = null;
|
||||
// check events
|
||||
BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
||||
EventInfo eventInfo = interfaceType.GetEvent(methodName, bindingFlags);
|
||||
if (eventInfo != null)
|
||||
{
|
||||
customAttrs = eventInfo.GetCustomAttributes(typeof(CorrelationAliasAttribute), true);
|
||||
if (customAttrs == null || customAttrs.Length == 0)
|
||||
{
|
||||
customAttrs = eventInfo.EventHandlerType.GetCustomAttributes(typeof(CorrelationAliasAttribute), true);
|
||||
}
|
||||
MethodInfo[] methInfo = eventInfo.EventHandlerType.GetMethods();
|
||||
methodInfo = methInfo[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
// check methods
|
||||
methodInfo = interfaceType.GetMethod(methodName, bindingFlags);
|
||||
if (methodInfo == null)
|
||||
{
|
||||
throw new MissingMethodException(interfaceType.AssemblyQualifiedName, methodName);
|
||||
}
|
||||
customAttrs = methodInfo.GetCustomAttributes(typeof(CorrelationAliasAttribute), true);
|
||||
}
|
||||
|
||||
foreach (CorrelationAliasAttribute aliasAttribute in customAttrs)
|
||||
{
|
||||
if (customAttrs.Length > 1)
|
||||
{
|
||||
Debug.Assert(aliasAttribute.Name != null);
|
||||
if (aliasAttribute.Name == null)
|
||||
throw new ArgumentNullException("ParameterName");
|
||||
}
|
||||
correlationAliases.Add(aliasAttribute.Name == null ? "" : aliasAttribute.Name, aliasAttribute);
|
||||
}
|
||||
}
|
||||
|
||||
private CorrelationPropertyValue GetCorrelationProperty(ParameterInfo[] parameters, string propertyName, string parameterName, string location)
|
||||
{
|
||||
for (int j = 0; parameters != null && j < parameters.Length; j++)
|
||||
{
|
||||
ParameterInfo param = parameters[j];
|
||||
if (param.Name == parameterName)
|
||||
{
|
||||
// parameter match
|
||||
return new CorrelationPropertyValue(propertyName, location, param.Position);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private object[] GetCorrelationParameterAttributes(Type type)
|
||||
{
|
||||
return type.GetCustomAttributes(typeof(CorrelationParameterAttribute), true);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class NonCorrelatedProvider : ICorrelationProvider
|
||||
{
|
||||
internal NonCorrelatedProvider()
|
||||
{
|
||||
}
|
||||
|
||||
ICollection<CorrelationProperty> ICorrelationProvider.ResolveCorrelationPropertyValues(Type interfaceType, string methodName, object[] methodArgs, bool provideInitializerTokens)
|
||||
{
|
||||
// non correlated
|
||||
// no values to return
|
||||
return null;
|
||||
}
|
||||
|
||||
bool ICorrelationProvider.IsInitializingMember(Type interfaceType, string memberName, object[] methodArgs)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,308 @@
|
||||
#region Using directives
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Workflow.ComponentModel;
|
||||
using System.Workflow.Runtime;
|
||||
using System.Workflow.Runtime.Hosting;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
using System.Xml;
|
||||
using System.Globalization;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace System.Workflow.Activities
|
||||
{
|
||||
internal interface ICorrelationProvider
|
||||
{
|
||||
ICollection<CorrelationProperty> ResolveCorrelationPropertyValues(Type interfaceType, string memberName, object[] methodArgs, bool provideInitializerTokens);
|
||||
bool IsInitializingMember(Type interfaceType, string memberName, object[] methodArgs);
|
||||
}
|
||||
|
||||
[AttributeUsageAttribute(AttributeTargets.Interface | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
|
||||
internal sealed class CorrelationProviderAttribute : Attribute
|
||||
{
|
||||
private Type correlationProviderType;
|
||||
|
||||
internal CorrelationProviderAttribute(Type correlationProviderType)
|
||||
{
|
||||
this.correlationProviderType = correlationProviderType;
|
||||
}
|
||||
|
||||
internal Type CorrelationProviderType
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.correlationProviderType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static class CorrelationService
|
||||
{
|
||||
internal static void Initialize(IServiceProvider context, Activity activity, Type interfaceType, string methodName, Guid instanceId)
|
||||
{
|
||||
if (activity == null)
|
||||
throw new ArgumentNullException("activity");
|
||||
if (interfaceType == null)
|
||||
throw new ArgumentNullException("interfaceType");
|
||||
if (methodName == null)
|
||||
throw new ArgumentNullException("methodName");
|
||||
|
||||
Subscribe(context, activity, interfaceType, methodName, null, instanceId);
|
||||
InitializeFollowers(context, interfaceType, methodName);
|
||||
}
|
||||
|
||||
internal static bool Subscribe(IServiceProvider context, Activity activity, Type interfaceType, string methodName, IActivityEventListener<QueueEventArgs> eventListener, Guid instanceId)
|
||||
{
|
||||
if (activity == null)
|
||||
throw new ArgumentNullException("activity");
|
||||
if (interfaceType == null)
|
||||
throw new ArgumentNullException("interfaceType");
|
||||
if (methodName == null)
|
||||
throw new ArgumentNullException("methodName");
|
||||
|
||||
WorkflowQueuingService queueService = (WorkflowQueuingService)context.GetService(typeof(WorkflowQueuingService));
|
||||
IComparable queueName = ResolveQueueName(activity, interfaceType, methodName);
|
||||
if (queueName != null)
|
||||
{
|
||||
// initializer
|
||||
WorkflowQueue queue = null;
|
||||
if (queueService.Exists(queueName))
|
||||
{
|
||||
queue = queueService.GetWorkflowQueue(queueName);
|
||||
queue.Enabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
queue = queueService.CreateWorkflowQueue(queueName, true);
|
||||
}
|
||||
|
||||
if (eventListener != null)
|
||||
{
|
||||
queue.RegisterForQueueItemAvailable(eventListener, activity.QualifiedName);
|
||||
WorkflowActivityTrace.Activity.TraceEvent(TraceEventType.Information, 0, "CorrelationService: activity '{0}' subscribing to QueueItemAvailable", activity.QualifiedName);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
SubscribeForCorrelationTokenInvalidation(activity, interfaceType, methodName, eventListener, instanceId);
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static bool Unsubscribe(IServiceProvider context, Activity activity, Type interfaceType, string methodName, IActivityEventListener<QueueEventArgs> eventListener)
|
||||
{
|
||||
if (activity == null)
|
||||
throw new ArgumentException("activity");
|
||||
if (interfaceType == null)
|
||||
throw new ArgumentNullException("interfaceType");
|
||||
if (methodName == null)
|
||||
throw new ArgumentNullException("methodName");
|
||||
|
||||
WorkflowQueuingService queueService = (WorkflowQueuingService)context.GetService(typeof(WorkflowQueuingService));
|
||||
IComparable queueName = ResolveQueueName(activity, interfaceType, methodName);
|
||||
if (queueName != null)
|
||||
{
|
||||
if (queueService.Exists(queueName))
|
||||
{
|
||||
queueService.GetWorkflowQueue(queueName).UnregisterForQueueItemAvailable(eventListener);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static IComparable ResolveQueueName(Activity activity, Type interfaceType, string methodName)
|
||||
{
|
||||
if (activity == null)
|
||||
throw new ArgumentNullException("activity");
|
||||
if (interfaceType == null)
|
||||
throw new ArgumentNullException("interfaceType");
|
||||
if (methodName == null)
|
||||
throw new ArgumentNullException("methodName");
|
||||
|
||||
// resolver will check for an explicit correlation provider,
|
||||
// if none present this will return an uncorrelated provider.
|
||||
// note, an uncorrelated methodName will always be an initializer
|
||||
if (CorrelationResolver.IsInitializingMember(interfaceType, methodName, null))
|
||||
{
|
||||
ICollection<CorrelationProperty> corrvalues = CorrelationResolver.ResolveCorrelationValues(interfaceType, methodName, null, true);
|
||||
return new EventQueueName(interfaceType, methodName, corrvalues);
|
||||
}
|
||||
|
||||
CorrelationToken reference = GetCorrelationToken(activity);
|
||||
if (!reference.Initialized)
|
||||
return null;
|
||||
|
||||
return new EventQueueName(interfaceType, methodName, reference.Properties);
|
||||
}
|
||||
|
||||
internal static void InvalidateCorrelationToken(Activity activity, Type interfaceType, string methodName, object[] messageArgs)
|
||||
{
|
||||
object correlationProvider = CorrelationResolver.GetCorrelationProvider(interfaceType);
|
||||
if (correlationProvider is NonCorrelatedProvider)
|
||||
return;
|
||||
|
||||
CorrelationToken reference = GetCorrelationToken(activity);
|
||||
ICollection<CorrelationProperty> correlationvalues = CorrelationResolver.ResolveCorrelationValues(interfaceType, methodName, messageArgs, false);
|
||||
|
||||
if (!CorrelationResolver.IsInitializingMember(interfaceType, methodName, messageArgs))
|
||||
{
|
||||
if (!reference.Initialized)
|
||||
throw new InvalidOperationException(SR.GetString(SR.Error_CorrelationNotInitialized, reference.Name, activity.QualifiedName));
|
||||
ValidateCorrelation(reference.Properties, correlationvalues, reference.Name, activity);
|
||||
return;
|
||||
}
|
||||
|
||||
// invalidate correlation token if methodName is an initializer
|
||||
reference.Initialize(activity, correlationvalues);
|
||||
}
|
||||
|
||||
private static CorrelationToken GetCorrelationToken(Activity activity)
|
||||
{
|
||||
DependencyProperty dependencyProperty = DependencyProperty.FromName("CorrelationToken", activity.GetType());
|
||||
if (dependencyProperty == null)
|
||||
dependencyProperty = DependencyProperty.FromName("CorrelationToken", activity.GetType().BaseType);
|
||||
CorrelationToken reference = activity.GetValue(dependencyProperty) as CorrelationToken;
|
||||
if (reference == null)
|
||||
throw new InvalidOperationException(SR.GetString(SR.Error_CorrelationTokenMissing, activity.Name));
|
||||
|
||||
CorrelationToken correlator = CorrelationTokenCollection.GetCorrelationToken(activity, reference.Name, reference.OwnerActivityName);
|
||||
if (correlator == null)
|
||||
throw new InvalidOperationException(SR.GetString(SR.Error_CorrelationTokenMissing, activity.Name));
|
||||
|
||||
return correlator;
|
||||
}
|
||||
|
||||
private static void ValidateCorrelation(ICollection<CorrelationProperty> initializerProperties, ICollection<CorrelationProperty> followerProperties, string memberName, Activity activity)
|
||||
{
|
||||
if (followerProperties == null && initializerProperties == null)
|
||||
return;
|
||||
|
||||
if (followerProperties == null || initializerProperties == null)
|
||||
throw new InvalidOperationException(SR.GetString(SR.Error_CorrelationViolationException, memberName, activity.QualifiedName));
|
||||
|
||||
if (initializerProperties.Count != followerProperties.Count)
|
||||
throw new InvalidOperationException(SR.GetString(SR.Error_CorrelationViolationException, memberName, activity.QualifiedName));
|
||||
|
||||
IEnumerator<CorrelationProperty> initializerValues = initializerProperties.GetEnumerator();
|
||||
IEnumerator<CorrelationProperty> followerValues = followerProperties.GetEnumerator();
|
||||
while (initializerValues.MoveNext() && followerValues.MoveNext())
|
||||
{
|
||||
IComparable initializerValue = initializerValues.Current.Value as IComparable;
|
||||
object followerValue = followerValues.Current.Value;
|
||||
|
||||
// Bug DevDiv2\DevDiv 552322 - http://vstfdevdiv.redmond.corp.microsoft.com:8080/DevDiv2/DevDiv/_workitems#_a=edit&id=552322
|
||||
// Reflection does not guarantee ordering, so the two collections (arrays) of
|
||||
// CorrelationProperties may not be in the same order, based on Name. So we need to check all the
|
||||
// elements of the followerProperties for the Name of the current initializerValue.
|
||||
// The collections MIGHT be in the same order. Before searching the followerProperties collection for an element with a matching
|
||||
// name, see if the current element in the initializerValues and followerValues enumerators have a matching name.
|
||||
// If they do match, just fall thru because followerValue is already set to followerValues.Current.Value;
|
||||
if (!initializerValues.Current.Name.Equals(followerValues.Current.Name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
CorrelationProperty followerProperty = null;
|
||||
IEnumerator<CorrelationProperty> followerEnumerator = followerProperties.GetEnumerator();
|
||||
while (followerEnumerator.MoveNext())
|
||||
{
|
||||
// We don't need to be concerned with culture here because the names we are comparing
|
||||
// are parameter names on methods in an interface.
|
||||
if (initializerValues.Current.Name.Equals(followerEnumerator.Current.Name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// We found a matching Name in the follower collection.
|
||||
// Saving the followerProperty rather than followerEnumerator.Current.Value here
|
||||
// because the latter could be null and still be correct. I need something
|
||||
// that indicates that we actually found a matching CorrelationProperty in the
|
||||
// collection. So instead of having a separate bool, I just have a reference
|
||||
// to the matching CorrelationProperty.
|
||||
followerProperty = followerEnumerator.Current;
|
||||
break;
|
||||
}
|
||||
// If we get here, the name of the parameter doesn't match, so just move to the next element in the
|
||||
// followerEnumerator.
|
||||
}
|
||||
// If we found a followerProperty with a matching name, use it.
|
||||
// In the highly, possibly impossible, event that we didn't find an element in the
|
||||
// followerProperties collection with a matching name, we fall thru with
|
||||
// followerValue = followerValues.Current.Value, which is exactly what the previous
|
||||
// code had, and we act just like we did before.
|
||||
if (followerProperty != null)
|
||||
{
|
||||
followerValue = followerProperty.Value;
|
||||
}
|
||||
}
|
||||
|
||||
if (initializerValue != null && (initializerValue.CompareTo(followerValue) != 0))
|
||||
throw new InvalidOperationException(SR.GetString(SR.Error_CorrelationViolationException, memberName, activity.QualifiedName));
|
||||
else if (initializerValues.Current.Value == null && followerValue == null)
|
||||
return;
|
||||
else if (initializerValue == null && followerValue != null && !followerValue.Equals(initializerValues.Current.Value))
|
||||
throw new InvalidOperationException(SR.GetString(SR.Error_CorrelationViolationException, memberName, activity.QualifiedName));
|
||||
}
|
||||
}
|
||||
|
||||
private static void SubscribeForCorrelationTokenInvalidation(Activity activity, Type interfaceType, string followermethodName, IActivityEventListener<QueueEventArgs> eventListener, Guid instanceId)
|
||||
{
|
||||
CorrelationToken reference = GetCorrelationToken(activity);
|
||||
CorrelationTokenInvalidatedHandler dataChangeEventListener = new CorrelationTokenInvalidatedHandler(interfaceType, followermethodName, eventListener, instanceId);
|
||||
reference.SubscribeForCorrelationTokenInitializedEvent(activity, dataChangeEventListener);
|
||||
}
|
||||
|
||||
private static void InitializeFollowers(IServiceProvider context, Type interfaceType, string followermethodName)
|
||||
{
|
||||
if (CorrelationResolver.IsInitializingMember(interfaceType, followermethodName, null))
|
||||
return;
|
||||
|
||||
EventInfo[] events = interfaceType.GetEvents();
|
||||
foreach (EventInfo e in events)
|
||||
{
|
||||
CreateFollowerEntry(context, interfaceType, followermethodName, e.Name);
|
||||
}
|
||||
}
|
||||
|
||||
private static void CreateFollowerEntry(IServiceProvider context, Type interfaceType, string followermethodName, string initializermethodName)
|
||||
{
|
||||
if (!CorrelationResolver.IsInitializingMember(interfaceType, initializermethodName, null))
|
||||
return;
|
||||
|
||||
WorkflowQueuingService queueSvcs = (WorkflowQueuingService)context.GetService(typeof(WorkflowQueuingService));
|
||||
FollowerQueueCreator follower = new FollowerQueueCreator(followermethodName);
|
||||
WorkflowActivityTrace.Activity.TraceEvent(TraceEventType.Information, 0, "Creating follower {0} on initializer {1}", interfaceType.Name + followermethodName, interfaceType.Name + initializermethodName);
|
||||
|
||||
ICollection<CorrelationProperty> corrValues = CorrelationResolver.ResolveCorrelationValues(interfaceType, initializermethodName, null, true);
|
||||
EventQueueName key = new EventQueueName(interfaceType, initializermethodName, corrValues);
|
||||
WorkflowQueue initializerQueue = null;
|
||||
if (queueSvcs.Exists(key))
|
||||
{
|
||||
initializerQueue = queueSvcs.GetWorkflowQueue(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
// traversed follower before initializer
|
||||
initializerQueue = queueSvcs.CreateWorkflowQueue(key, true);
|
||||
initializerQueue.Enabled = false;
|
||||
}
|
||||
|
||||
initializerQueue.RegisterForQueueItemArrived(follower);
|
||||
}
|
||||
|
||||
internal static void UninitializeFollowers(Type interfaceType, string initializer, WorkflowQueue initializerQueue)
|
||||
{
|
||||
if (!CorrelationResolver.IsInitializingMember(interfaceType, initializer, null))
|
||||
return;
|
||||
|
||||
EventInfo[] events = interfaceType.GetEvents();
|
||||
foreach (EventInfo e in events)
|
||||
{
|
||||
string follower = e.Name;
|
||||
if (!CorrelationResolver.IsInitializingMember(interfaceType, e.Name, null))
|
||||
initializerQueue.UnregisterForQueueItemArrived(new FollowerQueueCreator(follower));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Workflow.ComponentModel;
|
||||
using System.Workflow.Runtime;
|
||||
using System.Workflow.Runtime.Hosting;
|
||||
|
||||
namespace System.Workflow.Activities
|
||||
{
|
||||
[Serializable]
|
||||
internal sealed class CorrelationTokenInvalidatedHandler : IActivityEventListener<CorrelationTokenEventArgs>
|
||||
{
|
||||
IActivityEventListener<QueueEventArgs> eventHandler;
|
||||
EventQueueName queueName;
|
||||
Guid subscriptionId;
|
||||
Guid instanceId;
|
||||
|
||||
bool queueCreator;
|
||||
Type interfaceType;
|
||||
string followerOperation;
|
||||
|
||||
internal CorrelationTokenInvalidatedHandler(Type interfaceType, string operation, IActivityEventListener<QueueEventArgs> eventHandler, Guid instanceId)
|
||||
{
|
||||
this.eventHandler = eventHandler;
|
||||
this.interfaceType = interfaceType;
|
||||
this.followerOperation = operation;
|
||||
this.instanceId = instanceId;
|
||||
}
|
||||
|
||||
#region IActivityEventListener<CorrelationTokenEventArgs> Members
|
||||
void IActivityEventListener<CorrelationTokenEventArgs>.OnEvent(object sender, CorrelationTokenEventArgs dataChangeEventArgs)
|
||||
{
|
||||
if (sender == null)
|
||||
throw new ArgumentException("sender");
|
||||
if (dataChangeEventArgs == null)
|
||||
throw new ArgumentException("dataChangeEventArgs");
|
||||
|
||||
ActivityExecutionContext context = sender as ActivityExecutionContext;
|
||||
Activity activity = context.Activity;
|
||||
|
||||
ICollection<CorrelationProperty> correlationValues = dataChangeEventArgs.CorrelationToken.Properties;
|
||||
if (dataChangeEventArgs.IsInitializing)
|
||||
{
|
||||
CreateSubscription(this.instanceId, context, correlationValues);
|
||||
return;
|
||||
}
|
||||
|
||||
if (queueName != null)
|
||||
{
|
||||
if (!CorrelationResolver.IsInitializingMember(queueName.InterfaceType, queueName.MethodName,
|
||||
correlationValues == null ? null : new object[] { correlationValues }))
|
||||
{
|
||||
DeleteSubscription(context);
|
||||
}
|
||||
}
|
||||
|
||||
dataChangeEventArgs.CorrelationToken.UnsubscribeFromCorrelationTokenInitializedEvent(activity, this);
|
||||
}
|
||||
#endregion
|
||||
|
||||
private void CreateSubscription(Guid instanceId, ActivityExecutionContext context, ICollection<CorrelationProperty> correlationValues)
|
||||
{
|
||||
WorkflowQueuingService queueSvcs = context.GetService<WorkflowQueuingService>();
|
||||
EventQueueName queueId = new EventQueueName(this.interfaceType, this.followerOperation, correlationValues);
|
||||
|
||||
WorkflowQueue workflowQueue = null;
|
||||
if (!queueSvcs.Exists(queueId))
|
||||
{
|
||||
WorkflowActivityTrace.Activity.TraceEvent(TraceEventType.Information, 0, "CorrelationTokenInvalidatedHandler: creating q {0} ", queueId.GetHashCode());
|
||||
workflowQueue = queueSvcs.CreateWorkflowQueue(queueId, true);
|
||||
queueCreator = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
workflowQueue = queueSvcs.GetWorkflowQueue(queueId);
|
||||
}
|
||||
|
||||
if (this.eventHandler != null)
|
||||
{
|
||||
workflowQueue.RegisterForQueueItemAvailable(this.eventHandler);
|
||||
}
|
||||
|
||||
WorkflowSubscriptionService subscriptionService = (WorkflowSubscriptionService)context.GetService(typeof(WorkflowSubscriptionService));
|
||||
|
||||
MessageEventSubscription subscription = new MessageEventSubscription(queueId, instanceId);
|
||||
this.queueName = queueId;
|
||||
this.subscriptionId = subscription.SubscriptionId;
|
||||
subscription.InterfaceType = this.interfaceType;
|
||||
subscription.MethodName = this.followerOperation;
|
||||
|
||||
this.interfaceType = null;
|
||||
this.followerOperation = null;
|
||||
|
||||
if (correlationValues != null)
|
||||
{
|
||||
foreach (CorrelationProperty property in correlationValues)
|
||||
{
|
||||
subscription.CorrelationProperties.Add(property);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.eventHandler != null)
|
||||
return;
|
||||
|
||||
if (subscriptionService == null)
|
||||
return;
|
||||
subscriptionService.CreateSubscription(subscription);
|
||||
}
|
||||
|
||||
private void DeleteSubscription(ActivityExecutionContext context)
|
||||
{
|
||||
if (this.queueName == null)
|
||||
return;
|
||||
|
||||
WorkflowQueuingService queueSvcs = context.GetService<WorkflowQueuingService>();
|
||||
if (queueCreator)
|
||||
queueSvcs.DeleteWorkflowQueue(this.queueName);
|
||||
|
||||
if (this.eventHandler != null)
|
||||
return;
|
||||
|
||||
WorkflowSubscriptionService subscriptionService = context.GetService<WorkflowSubscriptionService>();
|
||||
if (subscriptionService != null)
|
||||
subscriptionService.DeleteSubscription(this.subscriptionId);
|
||||
|
||||
WorkflowActivityTrace.Activity.TraceEvent(TraceEventType.Information, 0, "CorrelationTokenInvalidatedHandler subscription deleted SubId {0} QueueId {1}", this.subscriptionId, this.queueName);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.Design;
|
||||
using System.ComponentModel.Design.Serialization;
|
||||
using System.Reflection;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Workflow.ComponentModel;
|
||||
using System.Workflow.ComponentModel.Design;
|
||||
using System.Workflow.ComponentModel.Serialization;
|
||||
using System.Workflow.Runtime;
|
||||
using System.Globalization;
|
||||
|
||||
namespace System.Workflow.Activities
|
||||
{
|
||||
internal sealed class CorrelationTokenTypeConverter : ExpandableObjectConverter
|
||||
{
|
||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
||||
{
|
||||
return (sourceType == typeof(string));
|
||||
}
|
||||
|
||||
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
||||
{
|
||||
return (destinationType == typeof(string));
|
||||
}
|
||||
|
||||
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
|
||||
{
|
||||
object convertedValue = null;
|
||||
string correlatorName = value as String;
|
||||
if (!String.IsNullOrEmpty(correlatorName))
|
||||
{
|
||||
foreach (object obj in GetStandardValues(context))
|
||||
{
|
||||
CorrelationToken correlator = obj as CorrelationToken;
|
||||
if (correlator != null && correlator.Name == correlatorName)
|
||||
{
|
||||
convertedValue = correlator;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (convertedValue == null)
|
||||
convertedValue = new CorrelationToken(correlatorName);
|
||||
}
|
||||
|
||||
return convertedValue;
|
||||
}
|
||||
|
||||
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
|
||||
{
|
||||
object convertedValue = null;
|
||||
CorrelationToken correlator = value as CorrelationToken;
|
||||
if (destinationType == typeof(string) && correlator != null)
|
||||
convertedValue = correlator.Name;
|
||||
return convertedValue;
|
||||
}
|
||||
|
||||
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
|
||||
{
|
||||
ArrayList values = new ArrayList();
|
||||
Activity activity = context.Instance as Activity;
|
||||
if (activity != null)
|
||||
{
|
||||
foreach (Activity preceedingActivity in GetPreceedingActivities(activity))
|
||||
{
|
||||
PropertyDescriptor correlatorProperty = TypeDescriptor.GetProperties(preceedingActivity)["CorrelationToken"] as PropertyDescriptor;
|
||||
if (correlatorProperty != null)
|
||||
{
|
||||
CorrelationToken correlator = correlatorProperty.GetValue(preceedingActivity) as CorrelationToken;
|
||||
if (correlator != null && !values.Contains(correlator))
|
||||
values.Add(correlator);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new StandardValuesCollection(values);
|
||||
}
|
||||
|
||||
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
|
||||
{
|
||||
PropertyDescriptorCollection properties = base.GetProperties(context, value, attributes);
|
||||
ArrayList props = new ArrayList(properties);
|
||||
return new PropertyDescriptorCollection((PropertyDescriptor[])props.ToArray(typeof(PropertyDescriptor)));
|
||||
}
|
||||
|
||||
//
|
||||
private IEnumerable GetPreceedingActivities(Activity startActivity)
|
||||
{
|
||||
Activity currentActivity = null;
|
||||
Stack<Activity> activityStack = new Stack<Activity>();
|
||||
activityStack.Push(startActivity);
|
||||
|
||||
while ((currentActivity = activityStack.Pop()) != null)
|
||||
{
|
||||
if (currentActivity.Parent != null)
|
||||
{
|
||||
foreach (Activity siblingActivity in currentActivity.Parent.Activities)
|
||||
{
|
||||
if (siblingActivity == currentActivity)
|
||||
break;
|
||||
|
||||
if (siblingActivity.Enabled)
|
||||
{
|
||||
if (siblingActivity is CompositeActivity)
|
||||
{
|
||||
foreach (Activity containedActivity in GetContainedActivities((CompositeActivity)siblingActivity))
|
||||
yield return containedActivity;
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return siblingActivity;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
activityStack.Push(currentActivity.Parent);
|
||||
}
|
||||
yield break;
|
||||
}
|
||||
|
||||
private IEnumerable GetContainedActivities(CompositeActivity activity)
|
||||
{
|
||||
if (!activity.Enabled)
|
||||
yield break;
|
||||
|
||||
foreach (Activity containedActivity in activity.Activities)
|
||||
{
|
||||
if (containedActivity is CompositeActivity)
|
||||
{
|
||||
foreach (Activity nestedActivity in GetContainedActivities((CompositeActivity)containedActivity))
|
||||
{
|
||||
if (nestedActivity.Enabled)
|
||||
yield return nestedActivity;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (containedActivity.Enabled)
|
||||
yield return containedActivity;
|
||||
}
|
||||
}
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Remoting;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
using System.Runtime.Remoting.Proxies;
|
||||
using System.Workflow.ComponentModel;
|
||||
using System.Workflow.Runtime;
|
||||
using System.Workflow.Runtime.Hosting;
|
||||
using System.Security.Permissions;
|
||||
using System.Globalization;
|
||||
|
||||
|
||||
namespace System.Workflow.Activities
|
||||
{
|
||||
internal sealed class ExternalDataExchangeBinder : Binder
|
||||
{
|
||||
Binder defltBinder;
|
||||
|
||||
internal ExternalDataExchangeBinder()
|
||||
{
|
||||
defltBinder = Type.DefaultBinder;
|
||||
}
|
||||
|
||||
public override MethodBase BindToMethod(BindingFlags bindingAttr,
|
||||
MethodBase[] match,
|
||||
ref object[] args,
|
||||
ParameterModifier[] modifiers,
|
||||
System.Globalization.CultureInfo culture,
|
||||
string[] names,
|
||||
out object state)
|
||||
{
|
||||
Object[] argsCopy = new Object[args.Length];
|
||||
args.CopyTo(argsCopy, 0);
|
||||
state = null;
|
||||
|
||||
try
|
||||
{
|
||||
return defltBinder.BindToMethod(bindingAttr, match, ref args, modifiers, culture, names, out state);
|
||||
}
|
||||
catch (MissingMethodException) //5% case where when passed null for params.
|
||||
{
|
||||
|
||||
if (match != null && match.Length != 0)
|
||||
{
|
||||
for (int i = 0; i < match.Length; ++i)
|
||||
{
|
||||
ParameterInfo[] methodParams = match[i].GetParameters();
|
||||
|
||||
if (methodParams.Length == argsCopy.Length)
|
||||
{
|
||||
for (int j = 0; j < methodParams.Length; ++j)
|
||||
{
|
||||
if (!methodParams[j].ParameterType.IsInstanceOfType(argsCopy[j]))
|
||||
{
|
||||
if (!(methodParams[j].ParameterType.IsArray && argsCopy[j] == null))
|
||||
break;
|
||||
}
|
||||
|
||||
if (j + 1 == methodParams.Length)
|
||||
return match[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override FieldInfo BindToField(BindingFlags bindingAttr,
|
||||
FieldInfo[] match,
|
||||
object value,
|
||||
CultureInfo culture)
|
||||
{
|
||||
return defltBinder.BindToField(bindingAttr, match, value, culture);
|
||||
}
|
||||
|
||||
public override MethodBase SelectMethod(BindingFlags bindingAttr,
|
||||
MethodBase[] match,
|
||||
Type[] types,
|
||||
ParameterModifier[] modifiers)
|
||||
{
|
||||
return defltBinder.SelectMethod(bindingAttr, match, types, modifiers);
|
||||
}
|
||||
|
||||
public override PropertyInfo SelectProperty(BindingFlags bindingAttr,
|
||||
PropertyInfo[] match,
|
||||
Type returnType,
|
||||
Type[] indexes,
|
||||
ParameterModifier[] modifiers
|
||||
)
|
||||
{
|
||||
return defltBinder.SelectProperty(bindingAttr, match, returnType, indexes, modifiers);
|
||||
}
|
||||
|
||||
public override object ChangeType(object value,
|
||||
Type type,
|
||||
CultureInfo culture
|
||||
)
|
||||
{
|
||||
return defltBinder.ChangeType(value, type, culture);
|
||||
}
|
||||
|
||||
public override void ReorderArgumentArray(ref object[] args,
|
||||
object state
|
||||
)
|
||||
{
|
||||
defltBinder.ReorderArgumentArray(ref args, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,381 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Collections;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Reflection;
|
||||
using System.Workflow.ComponentModel;
|
||||
using System.Workflow.Runtime;
|
||||
using System.Workflow.Runtime.Configuration;
|
||||
using System.Workflow.Runtime.Hosting;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.Configuration;
|
||||
|
||||
namespace System.Workflow.Activities
|
||||
{
|
||||
internal interface IDeliverMessage
|
||||
{
|
||||
object[] PrepareEventArgsArray(object sender, ExternalDataEventArgs eventArgs, out object workItem, out IPendingWork workHandler);
|
||||
void DeliverMessage(ExternalDataEventArgs eventArgs, IComparable queueName, object message, object workItem, IPendingWork workHandler);
|
||||
}
|
||||
|
||||
[Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")]
|
||||
public class ExternalDataExchangeServiceSection : ConfigurationSection
|
||||
{
|
||||
private const string _services = "Services";
|
||||
|
||||
/// <summary> The providers to be instantiated by the service container. </summary>
|
||||
[ConfigurationProperty(_services, DefaultValue = null)]
|
||||
public WorkflowRuntimeServiceElementCollection Services
|
||||
{
|
||||
get
|
||||
{
|
||||
return (WorkflowRuntimeServiceElementCollection)base[_services];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")]
|
||||
public class ExternalDataExchangeService : WorkflowRuntimeService
|
||||
{
|
||||
Dictionary<int, WorkflowMessageEventHandler> eventHandlers = null;
|
||||
object handlersLock = new object();
|
||||
private const string configurationSectionAttributeName = "ConfigurationSection";
|
||||
ExternalDataExchangeServiceSection settings = null;
|
||||
IDeliverMessage enqueueMessageWrapper = null;
|
||||
List<object> services;
|
||||
object servicesLock = new object();
|
||||
|
||||
public ExternalDataExchangeService()
|
||||
{
|
||||
this.eventHandlers = new Dictionary<int, WorkflowMessageEventHandler>();
|
||||
this.services = new List<object>();
|
||||
this.enqueueMessageWrapper = new EnqueueMessageWrapper(this);
|
||||
}
|
||||
|
||||
public ExternalDataExchangeService(string configSectionName)
|
||||
: this()
|
||||
{
|
||||
if (configSectionName == null)
|
||||
throw new ArgumentNullException("configSectionName");
|
||||
|
||||
settings = ConfigurationManager.GetSection(configSectionName) as ExternalDataExchangeServiceSection;
|
||||
if (settings == null)
|
||||
throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
|
||||
SR.GetString(SR.Error_ConfigurationSectionNotFound), configSectionName));
|
||||
}
|
||||
|
||||
public ExternalDataExchangeService(NameValueCollection parameters)
|
||||
: this()
|
||||
{
|
||||
if (parameters == null)
|
||||
throw new ArgumentNullException("parameters");
|
||||
string configurationSectionName = null;
|
||||
|
||||
foreach (string key in parameters.Keys)
|
||||
{
|
||||
if (key.Equals(configurationSectionAttributeName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
configurationSectionName = parameters[key];
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException(
|
||||
String.Format(Thread.CurrentThread.CurrentCulture, SR.GetString(SR.Error_UnknownConfigurationParameter), key), "parameters");
|
||||
}
|
||||
}
|
||||
if (configurationSectionName != null)
|
||||
{
|
||||
settings = ConfigurationManager.GetSection(configurationSectionName) as ExternalDataExchangeServiceSection;
|
||||
if (settings == null)
|
||||
throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
|
||||
SR.GetString(SR.Error_ConfigurationSectionNotFound), configurationSectionName));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public ExternalDataExchangeService(ExternalDataExchangeServiceSection settings)
|
||||
: this()
|
||||
{
|
||||
if (settings == null)
|
||||
throw new ArgumentNullException("settings");
|
||||
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
internal ReadOnlyCollection<object> GetAllServices()
|
||||
{
|
||||
ReadOnlyCollection<object> collection;
|
||||
lock (this.servicesLock)
|
||||
{
|
||||
collection = this.services.AsReadOnly();
|
||||
}
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
if (settings != null)
|
||||
{
|
||||
foreach (WorkflowRuntimeServiceElement service in settings.Services)
|
||||
{
|
||||
AddService(ServiceFromSettings(service));
|
||||
}
|
||||
}
|
||||
|
||||
if (this.Runtime != null)
|
||||
{
|
||||
base.Start();
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetEnqueueMessageWrapper(IDeliverMessage wrapper)
|
||||
{
|
||||
this.enqueueMessageWrapper = wrapper;
|
||||
foreach (WorkflowMessageEventHandler eventHandler in this.eventHandlers.Values)
|
||||
{
|
||||
eventHandler.EnqueueWrapper = wrapper;
|
||||
}
|
||||
}
|
||||
|
||||
// Todo: This is duplicate of code in WorkflowRuntime
|
||||
internal object ServiceFromSettings(WorkflowRuntimeServiceElement serviceSettings)
|
||||
{
|
||||
object service = null;
|
||||
|
||||
Type t = Type.GetType(serviceSettings.Type, true);
|
||||
|
||||
ConstructorInfo serviceProviderAndSettingsConstructor = null;
|
||||
ConstructorInfo serviceProviderConstructor = null;
|
||||
ConstructorInfo settingsConstructor = null;
|
||||
|
||||
foreach (ConstructorInfo ci in t.GetConstructors())
|
||||
{
|
||||
ParameterInfo[] pi = ci.GetParameters();
|
||||
if (pi.Length == 1)
|
||||
{
|
||||
if (typeof(IServiceProvider).IsAssignableFrom(pi[0].ParameterType))
|
||||
{
|
||||
serviceProviderConstructor = ci;
|
||||
}
|
||||
else if (typeof(NameValueCollection).IsAssignableFrom(pi[0].ParameterType))
|
||||
{
|
||||
settingsConstructor = ci;
|
||||
}
|
||||
}
|
||||
else if (pi.Length == 2)
|
||||
{
|
||||
if (typeof(IServiceProvider).IsAssignableFrom(pi[0].ParameterType)
|
||||
&& typeof(NameValueCollection).IsAssignableFrom(pi[1].ParameterType))
|
||||
{
|
||||
serviceProviderAndSettingsConstructor = ci;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (serviceProviderAndSettingsConstructor != null)
|
||||
{
|
||||
service = serviceProviderAndSettingsConstructor.Invoke(
|
||||
new object[] { Runtime, serviceSettings.Parameters });
|
||||
}
|
||||
else if (serviceProviderConstructor != null)
|
||||
{
|
||||
service = serviceProviderConstructor.Invoke(new object[] { Runtime });
|
||||
}
|
||||
else if (settingsConstructor != null)
|
||||
{
|
||||
service = settingsConstructor.Invoke(new object[] { serviceSettings.Parameters });
|
||||
}
|
||||
else
|
||||
{
|
||||
service = Activator.CreateInstance(t);
|
||||
}
|
||||
return service;
|
||||
}
|
||||
|
||||
public virtual void AddService(object service)
|
||||
{
|
||||
if (service == null)
|
||||
throw new ArgumentNullException("service");
|
||||
|
||||
InterceptService(service, true);
|
||||
if (this.Runtime != null)
|
||||
{
|
||||
this.Runtime.AddService(service);
|
||||
}
|
||||
else
|
||||
{
|
||||
lock (this.servicesLock)
|
||||
{
|
||||
this.services.Add(service);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void RemoveService(object service)
|
||||
{
|
||||
if (service == null)
|
||||
throw new ArgumentNullException("service");
|
||||
|
||||
InterceptService(service, false);
|
||||
if (this.Runtime != null)
|
||||
{
|
||||
this.Runtime.RemoveService(service);
|
||||
}
|
||||
else
|
||||
{
|
||||
lock (this.servicesLock)
|
||||
{
|
||||
this.services.Remove(service);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual object GetService(Type serviceType)
|
||||
{
|
||||
if (serviceType == null)
|
||||
throw new ArgumentNullException("serviceType");
|
||||
|
||||
if (this.Runtime != null)
|
||||
{
|
||||
return this.Runtime.GetService(serviceType);
|
||||
}
|
||||
else
|
||||
{
|
||||
lock (this.servicesLock)
|
||||
{
|
||||
foreach (object service in this.services)
|
||||
{
|
||||
if (serviceType.IsAssignableFrom(service.GetType()))
|
||||
{
|
||||
return service;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void InterceptService(object service, bool add)
|
||||
{
|
||||
bool isDataExchangeService = false;
|
||||
Type[] interfaceTypes = service.GetType().GetInterfaces();
|
||||
foreach (Type type in interfaceTypes)
|
||||
{
|
||||
object[] attributes = type.GetCustomAttributes(typeof(ExternalDataExchangeAttribute), false);
|
||||
if (attributes.Length == 0)
|
||||
continue;
|
||||
|
||||
if (this.Runtime != null && this.Runtime.GetService(type) != null && add)
|
||||
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Error_ExternalDataExchangeServiceExists), type));
|
||||
|
||||
isDataExchangeService = true;
|
||||
EventInfo[] events = type.GetEvents();
|
||||
if (events == null)
|
||||
continue;
|
||||
|
||||
foreach (EventInfo e in events)
|
||||
{
|
||||
WorkflowMessageEventHandler handler = null;
|
||||
int hash = type.GetHashCode() ^ e.Name.GetHashCode();
|
||||
lock (handlersLock)
|
||||
{
|
||||
if (!this.eventHandlers.ContainsKey(hash))
|
||||
{
|
||||
handler = new WorkflowMessageEventHandler(type, e, this.enqueueMessageWrapper);
|
||||
this.eventHandlers.Add(hash, handler);
|
||||
}
|
||||
else
|
||||
{
|
||||
handler = this.eventHandlers[hash];
|
||||
}
|
||||
}
|
||||
AddRemove(service, handler.Delegate, add, e.Name);
|
||||
}
|
||||
}
|
||||
if (!isDataExchangeService)
|
||||
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Error_ServiceMissingExternalDataExchangeInterface)));
|
||||
}
|
||||
|
||||
private void AddRemove(object addedservice, Delegate delg, bool add, string eventName)
|
||||
{
|
||||
try
|
||||
{
|
||||
string eventAction;
|
||||
if (add)
|
||||
eventAction = "add_" + eventName;
|
||||
else
|
||||
eventAction = "remove_" + eventName;
|
||||
|
||||
Type serviceType = addedservice.GetType();
|
||||
if (delg != null)
|
||||
{
|
||||
// add or remove interception handler
|
||||
object[] del = { delg };
|
||||
serviceType.InvokeMember(eventAction, BindingFlags.InvokeMethod, null, addedservice, del, null);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (IsIrrecoverableException(e))
|
||||
{
|
||||
throw;
|
||||
}
|
||||
// cannot intercept this event
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool IsIrrecoverableException(Exception e)
|
||||
{
|
||||
return ((e is OutOfMemoryException) ||
|
||||
(e is StackOverflowException) ||
|
||||
(e is ThreadInterruptedException) ||
|
||||
(e is ThreadAbortException));
|
||||
}
|
||||
|
||||
class EnqueueMessageWrapper : IDeliverMessage
|
||||
{
|
||||
ExternalDataExchangeService eds;
|
||||
|
||||
public EnqueueMessageWrapper(ExternalDataExchangeService eds)
|
||||
{
|
||||
this.eds = eds;
|
||||
}
|
||||
|
||||
public object[] PrepareEventArgsArray(object sender, ExternalDataEventArgs eventArgs, out object workItem, out IPendingWork workHandler)
|
||||
{
|
||||
// remove the batch items from the event args, only the runtime needs this data
|
||||
// and it is not necessarily serializable.
|
||||
workItem = eventArgs.WorkItem;
|
||||
eventArgs.WorkItem = null;
|
||||
workHandler = eventArgs.WorkHandler;
|
||||
eventArgs.WorkHandler = null;
|
||||
|
||||
return new object[] { sender, eventArgs };
|
||||
}
|
||||
public void DeliverMessage(ExternalDataEventArgs eventArgs, IComparable queueName, object message, object workItem, IPendingWork workHandler)
|
||||
{
|
||||
WorkflowInstance workflowInstance = this.eds.Runtime.GetWorkflow(eventArgs.InstanceId);
|
||||
if (eventArgs.WaitForIdle)
|
||||
{
|
||||
workflowInstance.EnqueueItemOnIdle(queueName, message, workHandler, workItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
workflowInstance.EnqueueItem(queueName, message, workHandler, workItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
#region Using directives
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Workflow.ComponentModel;
|
||||
using System.Workflow.Runtime;
|
||||
using System.Workflow.Runtime.Hosting;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace System.Workflow.Activities
|
||||
{
|
||||
[Serializable]
|
||||
internal sealed class FollowerQueueCreator : IActivityEventListener<QueueEventArgs>
|
||||
{
|
||||
string followerOperation;
|
||||
object sync = new object();
|
||||
|
||||
internal FollowerQueueCreator(string operation)
|
||||
{
|
||||
this.followerOperation = operation;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
return false;
|
||||
FollowerQueueCreator equalsObject = obj as FollowerQueueCreator;
|
||||
if (this.followerOperation == equalsObject.followerOperation)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this.followerOperation.GetHashCode();
|
||||
}
|
||||
|
||||
#region IActivityEventListener<QueueEventArgs> Members
|
||||
|
||||
void IActivityEventListener<QueueEventArgs>.OnEvent(object sender, QueueEventArgs args)
|
||||
{
|
||||
lock (sync)
|
||||
{
|
||||
WorkflowQueue queue = (WorkflowQueue)sender;
|
||||
|
||||
// create the queue after extracting the correlation values from the message
|
||||
EventQueueName staticId = (EventQueueName)queue.QueueName;
|
||||
WorkflowActivityTrace.Activity.TraceEvent(TraceEventType.Information, 0, "FollowerQueueCreator: initialized on operation {0} for follower {1}", staticId.InterfaceType.Name + staticId.MethodName, this.followerOperation);
|
||||
|
||||
IMethodMessage message = queue.Peek() as IMethodMessage;
|
||||
|
||||
ICollection<CorrelationProperty> corrValues = CorrelationResolver.ResolveCorrelationValues(staticId.InterfaceType, staticId.MethodName, message.Args, false);
|
||||
|
||||
EventQueueName queueName = new EventQueueName(staticId.InterfaceType, this.followerOperation, corrValues);
|
||||
if (!queue.QueuingService.Exists(queueName))
|
||||
{
|
||||
WorkflowActivityTrace.Activity.TraceEvent(TraceEventType.Information, 0, "FollowerQueueCreator::CreateQueue creating q {0}", queueName.GetHashCode());
|
||||
queue.QueuingService.CreateWorkflowQueue(queueName, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
#region Using directives
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Workflow.ComponentModel;
|
||||
using System.Workflow.Runtime;
|
||||
using System.Workflow.Runtime.Hosting;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace System.Workflow.Activities
|
||||
{
|
||||
[Serializable]
|
||||
internal sealed class FollowerQueueCreator : IActivityEventListener<QueueEventArgs>
|
||||
{
|
||||
string followerOperation;
|
||||
object [....] = new object();
|
||||
|
||||
internal FollowerQueueCreator(string operation)
|
||||
{
|
||||
this.followerOperation = operation;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
return false;
|
||||
FollowerQueueCreator equalsObject = obj as FollowerQueueCreator;
|
||||
if (this.followerOperation == equalsObject.followerOperation)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this.followerOperation.GetHashCode();
|
||||
}
|
||||
|
||||
#region IActivityEventListener<QueueEventArgs> Members
|
||||
|
||||
void IActivityEventListener<QueueEventArgs>.OnEvent(object sender, QueueEventArgs args)
|
||||
{
|
||||
lock ([....])
|
||||
{
|
||||
WorkflowQueue queue = (WorkflowQueue)sender;
|
||||
|
||||
// create the queue after extracting the correlation values from the message
|
||||
EventQueueName staticId = (EventQueueName)queue.QueueName;
|
||||
WorkflowActivityTrace.Activity.TraceEvent(TraceEventType.Information, 0, "FollowerQueueCreator: initialized on operation {0} for follower {1}", staticId.InterfaceType.Name + staticId.MethodName, this.followerOperation);
|
||||
|
||||
IMethodMessage message = queue.Peek() as IMethodMessage;
|
||||
|
||||
ICollection<CorrelationProperty> corrValues = CorrelationResolver.ResolveCorrelationValues(staticId.InterfaceType, staticId.MethodName, message.Args, false);
|
||||
|
||||
EventQueueName queueName = new EventQueueName(staticId.InterfaceType, this.followerOperation, corrValues);
|
||||
if (!queue.QueuingService.Exists(queueName))
|
||||
{
|
||||
WorkflowActivityTrace.Activity.TraceEvent(TraceEventType.Information, 0, "FollowerQueueCreator::CreateQueue creating q {0}", queueName.GetHashCode());
|
||||
queue.QueuingService.CreateWorkflowQueue(queueName, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
#region Using directives
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
using System.Security.Principal;
|
||||
#endregion
|
||||
|
||||
namespace System.Workflow.Activities
|
||||
{
|
||||
[Serializable]
|
||||
internal sealed class IdentityContextData : ILogicalThreadAffinative, ISerializable
|
||||
{
|
||||
internal const string IdentityContext = "__identitycontext__";
|
||||
|
||||
String identity;
|
||||
|
||||
internal IdentityContextData(String identity)
|
||||
{
|
||||
this.identity = identity;
|
||||
}
|
||||
|
||||
private IdentityContextData(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
SerializationInfoEnumerator enumerator = info.GetEnumerator();
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
if (enumerator.Name.Equals("identity"))
|
||||
{
|
||||
this.identity = (String)enumerator.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SecurityPermission( SecurityAction.Demand, SerializationFormatter = true)]
|
||||
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
if (this.identity != null)
|
||||
info.AddValue("identity", identity.ToString());
|
||||
}
|
||||
|
||||
internal String Identity
|
||||
{
|
||||
get
|
||||
{
|
||||
return identity;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Workflow.ComponentModel;
|
||||
using System.Workflow.Runtime;
|
||||
using System.Workflow.Runtime.Hosting;
|
||||
|
||||
namespace System.Workflow.Activities
|
||||
{
|
||||
[Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")]
|
||||
public abstract class WorkflowSubscriptionService
|
||||
{
|
||||
public abstract void CreateSubscription(MessageEventSubscription subscription);
|
||||
public abstract void DeleteSubscription(Guid subscriptionId);
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
[Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")]
|
||||
public class MessageEventSubscription
|
||||
{
|
||||
Type interfaceType;
|
||||
String operation;
|
||||
List<CorrelationProperty> predicates;
|
||||
Guid subscriptionId;
|
||||
Guid workflowInstanceId;
|
||||
IComparable queueName;
|
||||
|
||||
protected MessageEventSubscription()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public MessageEventSubscription(IComparable queueName, Guid instanceId)
|
||||
: this(queueName, instanceId, Guid.NewGuid())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public MessageEventSubscription(IComparable queueName, Guid instanceId, Guid subscriptionId)
|
||||
: this(queueName, instanceId, null, null, subscriptionId)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public MessageEventSubscription(IComparable queueName, Guid subscriptionId, Type interfaceType, String operation)
|
||||
: this(queueName, Guid.Empty, interfaceType, operation, subscriptionId)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public MessageEventSubscription(IComparable queueName, Guid instanceId, Type interfaceType, String operation, Guid subscriptionId)
|
||||
{
|
||||
this.queueName = queueName;
|
||||
this.workflowInstanceId = instanceId;
|
||||
this.subscriptionId = subscriptionId;
|
||||
this.interfaceType = interfaceType;
|
||||
this.operation = operation;
|
||||
this.predicates = new List<CorrelationProperty>();
|
||||
}
|
||||
|
||||
public virtual Type InterfaceType
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.interfaceType;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.interfaceType = value;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual String MethodName
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.operation;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.operation = value;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual ICollection<CorrelationProperty> CorrelationProperties
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.predicates;
|
||||
}
|
||||
}
|
||||
|
||||
//A Unique id for this subscription. It is needed because
|
||||
//QueueName is not always guaranteed to be Unique.
|
||||
//Needed in case of Multiple Subscription on Same Queue
|
||||
public virtual Guid SubscriptionId
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.subscriptionId;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual IComparable QueueName
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.queueName;
|
||||
}
|
||||
protected set
|
||||
{
|
||||
this.queueName = value;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual Guid WorkflowInstanceId
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.workflowInstanceId;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
#pragma warning disable 1634, 1691
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Workflow.ComponentModel;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Workflow.Runtime;
|
||||
|
||||
namespace System.Workflow.Activities
|
||||
{
|
||||
[Serializable]
|
||||
[Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")]
|
||||
public sealed class EventQueueName : IComparable
|
||||
{
|
||||
Type interfaceType;
|
||||
string operation;
|
||||
CorrelationProperty[] correlationValues;
|
||||
string activityId;
|
||||
|
||||
[NonSerialized]
|
||||
string assemblyQualifiedName;
|
||||
|
||||
[NonSerialized]
|
||||
String stringifiedKey;
|
||||
|
||||
private string AssemblyQualifiedName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (assemblyQualifiedName == null)
|
||||
{
|
||||
assemblyQualifiedName = this.interfaceType.AssemblyQualifiedName;
|
||||
}
|
||||
return assemblyQualifiedName;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public EventQueueName(Type interfaceType, string operation)
|
||||
{
|
||||
if (interfaceType == null)
|
||||
throw new ArgumentNullException("interfaceType");
|
||||
if (operation == null)
|
||||
throw new ArgumentNullException("operation");
|
||||
|
||||
this.interfaceType = interfaceType;
|
||||
this.operation = operation;
|
||||
}
|
||||
|
||||
public EventQueueName(Type interfaceType, string operation, ICollection<CorrelationProperty> propertyValues)
|
||||
: this(interfaceType, operation)
|
||||
{
|
||||
if (propertyValues != null)
|
||||
{
|
||||
this.correlationValues = new CorrelationProperty[propertyValues.Count];
|
||||
propertyValues.CopyTo(this.correlationValues, 0);
|
||||
}
|
||||
}
|
||||
|
||||
internal EventQueueName(Type interfaceType, string operation, string activityId)
|
||||
: this(interfaceType, operation)
|
||||
{
|
||||
this.activityId = activityId;
|
||||
}
|
||||
|
||||
// properties
|
||||
public Type InterfaceType
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.interfaceType;
|
||||
}
|
||||
}
|
||||
|
||||
public string MethodName
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.operation;
|
||||
}
|
||||
}
|
||||
|
||||
public CorrelationProperty[] GetCorrelationValues()
|
||||
{
|
||||
return this.correlationValues;
|
||||
}
|
||||
|
||||
public int CompareTo(Object toCompare)
|
||||
{
|
||||
if (toCompare is EventQueueName)
|
||||
return this.CompareTo(toCompare as EventQueueName);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
// IComparable implementation
|
||||
public int CompareTo(EventQueueName eventQueueName)
|
||||
{
|
||||
if (eventQueueName == null)
|
||||
return -1;
|
||||
|
||||
// compare operation
|
||||
int compared = StringComparer.Ordinal.Compare(this.MethodName, eventQueueName.MethodName);
|
||||
|
||||
if (compared == 0)
|
||||
{
|
||||
// compare type names
|
||||
#pragma warning disable 56506
|
||||
compared = StringComparer.Ordinal.Compare(AssemblyQualifiedName, eventQueueName.AssemblyQualifiedName);
|
||||
#pragma warning restore 56506
|
||||
|
||||
if (compared == 0)
|
||||
{
|
||||
if (this.correlationValues != null)
|
||||
{
|
||||
compared = (eventQueueName.correlationValues != null) ? (this.correlationValues.Length - eventQueueName.correlationValues.Length) : -1;
|
||||
|
||||
if (compared == 0)
|
||||
{
|
||||
// compare correlation values
|
||||
for (int i = 0; i < this.correlationValues.Length; i++)
|
||||
{
|
||||
if (this.correlationValues[i] == null || eventQueueName.correlationValues[i] == null)
|
||||
{
|
||||
compared = -1;
|
||||
break; // match failed
|
||||
}
|
||||
|
||||
object leftValue = this.correlationValues[i].Value;
|
||||
object rightValue = FindCorrelationValue(this.correlationValues[i].Name, eventQueueName.correlationValues);
|
||||
|
||||
#pragma warning suppress 56506
|
||||
if (leftValue == null && rightValue == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// do the explicit equals check
|
||||
if (leftValue != null)
|
||||
{
|
||||
IComparable comparable = leftValue as IComparable;
|
||||
if (comparable != null)
|
||||
{
|
||||
compared = comparable.CompareTo(rightValue);
|
||||
if (compared != 0)
|
||||
{
|
||||
break; // match failed
|
||||
}
|
||||
}
|
||||
else if ((!leftValue.Equals(rightValue)))
|
||||
{
|
||||
compared = -1;
|
||||
break; // match failed
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
compared = -1;
|
||||
break; // match failed
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return compared;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
EventQueueName k = obj as EventQueueName;
|
||||
//Without the cast we end up in op_Equality below
|
||||
if ((object)k == null)
|
||||
return false;
|
||||
|
||||
return 0 == CompareTo(k);
|
||||
}
|
||||
|
||||
public static bool operator ==(EventQueueName queueKey1, EventQueueName queueKey2)
|
||||
{
|
||||
bool equality = false;
|
||||
|
||||
if ((object)queueKey1 != null)
|
||||
{
|
||||
if ((object)queueKey2 != null)
|
||||
{
|
||||
equality = (0 == queueKey1.CompareTo(queueKey2));
|
||||
}
|
||||
}
|
||||
else if ((object)queueKey2 == null)
|
||||
{
|
||||
equality = true;
|
||||
}
|
||||
|
||||
return equality;
|
||||
}
|
||||
|
||||
public static bool operator !=(EventQueueName queueKey1, EventQueueName queueKey2)
|
||||
{
|
||||
return !(queueKey1 == queueKey2);
|
||||
}
|
||||
|
||||
public static bool operator <(EventQueueName queueKey1, EventQueueName queueKey2)
|
||||
{
|
||||
if (queueKey1 == null)
|
||||
throw new ArgumentNullException("queueKey1");
|
||||
|
||||
if (queueKey2 == null)
|
||||
throw new ArgumentNullException("queueKey2");
|
||||
|
||||
return (queueKey1.CompareTo(queueKey2) < 0);
|
||||
}
|
||||
|
||||
public static bool operator >(EventQueueName queueKey1, EventQueueName queueKey2)
|
||||
{
|
||||
if (queueKey1 == null)
|
||||
throw new ArgumentNullException("queueKey1");
|
||||
|
||||
if (queueKey2 == null)
|
||||
throw new ArgumentNullException("queueKey2");
|
||||
|
||||
return (queueKey1.CompareTo(queueKey2) > 0);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
if (String.IsNullOrEmpty(this.activityId))
|
||||
return (AssemblyQualifiedName.GetHashCode() ^ this.operation.GetHashCode());
|
||||
|
||||
return (AssemblyQualifiedName.GetHashCode() ^ this.operation.GetHashCode() ^ this.activityId.GetHashCode());
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (stringifiedKey == null)
|
||||
{
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
|
||||
stringBuilder.AppendLine("Message Properties");
|
||||
stringBuilder.AppendLine("Interface Type:" + this.interfaceType.ToString());
|
||||
stringBuilder.AppendLine("Method Name:" + this.operation.ToString());
|
||||
stringBuilder.AppendLine("CorrelationValues:");
|
||||
|
||||
if (correlationValues != null)
|
||||
{
|
||||
foreach (CorrelationProperty pred in correlationValues)
|
||||
{
|
||||
if (pred != null && pred.Value != null)
|
||||
stringBuilder.AppendLine(pred.Value.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
stringifiedKey = stringBuilder.ToString();
|
||||
}
|
||||
|
||||
return stringifiedKey;
|
||||
}
|
||||
|
||||
object FindCorrelationValue(string name, CorrelationProperty[] correlationValues)
|
||||
{
|
||||
object value = null;
|
||||
foreach (CorrelationProperty property in correlationValues)
|
||||
{
|
||||
if (property != null && property.Name == name)
|
||||
{
|
||||
value = property.Value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,342 @@
|
||||
#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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
#region Using directives
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Workflow.ComponentModel;
|
||||
using System.Workflow.Runtime;
|
||||
using System.Workflow.Runtime.Hosting;
|
||||
using System.Security.Principal;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace System.Workflow.Activities
|
||||
{
|
||||
[AttributeUsageAttribute(AttributeTargets.Interface, AllowMultiple = false, Inherited = false)]
|
||||
[Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")]
|
||||
public sealed class ExternalDataExchangeAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
[AttributeUsageAttribute(AttributeTargets.Event | AttributeTargets.Method, AllowMultiple = false)]
|
||||
[Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")]
|
||||
public sealed class CorrelationInitializerAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsageAttribute(AttributeTargets.Interface, AllowMultiple = true)]
|
||||
[Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")]
|
||||
public sealed class CorrelationParameterAttribute : Attribute
|
||||
{
|
||||
private string name = string.Empty;
|
||||
public CorrelationParameterAttribute(string name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsageAttribute(AttributeTargets.Delegate | AttributeTargets.Event | AttributeTargets.Method, AllowMultiple = true)]
|
||||
[Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")]
|
||||
public sealed class CorrelationAliasAttribute : Attribute
|
||||
{
|
||||
private string path;
|
||||
private string name;
|
||||
|
||||
public CorrelationAliasAttribute(String name, String path)
|
||||
{
|
||||
this.path = path;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
|
||||
public String Path
|
||||
{
|
||||
get
|
||||
{
|
||||
return path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
[Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")]
|
||||
public class ExternalDataEventArgs : EventArgs
|
||||
{
|
||||
Guid instanceId;
|
||||
object batchworkItem;
|
||||
IPendingWork batchworkHandler;
|
||||
String identity;
|
||||
bool waitForIdle;
|
||||
|
||||
public ExternalDataEventArgs()
|
||||
: this(Guid.Empty, null, null, false)
|
||||
{
|
||||
}
|
||||
|
||||
public ExternalDataEventArgs(Guid instanceId)
|
||||
: this(instanceId, null, null, false)
|
||||
{
|
||||
}
|
||||
|
||||
public ExternalDataEventArgs(Guid instanceId, IPendingWork workHandler, object workItem, bool waitForIdle)
|
||||
{
|
||||
this.instanceId = instanceId;
|
||||
this.batchworkHandler = workHandler;
|
||||
this.batchworkItem = workItem;
|
||||
this.waitForIdle = waitForIdle;
|
||||
}
|
||||
|
||||
public ExternalDataEventArgs(Guid instanceId, IPendingWork workHandler, object workItem)
|
||||
: this(instanceId, workHandler, workItem, false)
|
||||
{
|
||||
}
|
||||
|
||||
public Guid InstanceId
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.instanceId;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.instanceId = value;
|
||||
}
|
||||
}
|
||||
|
||||
public object WorkItem
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.batchworkItem;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.batchworkItem = value;
|
||||
}
|
||||
}
|
||||
|
||||
public IPendingWork WorkHandler
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.batchworkHandler;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.batchworkHandler = value;
|
||||
}
|
||||
}
|
||||
|
||||
public String Identity
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.identity;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.identity = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool WaitForIdle
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.waitForIdle;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.waitForIdle = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Workflow.ComponentModel;
|
||||
using System.Workflow.Runtime;
|
||||
using System.Workflow.Runtime.Hosting;
|
||||
using System.Security.Principal;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace System.Workflow.Activities
|
||||
{
|
||||
[Serializable]
|
||||
[Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")]
|
||||
public sealed class EventDeliveryFailedException : SystemException
|
||||
{
|
||||
public EventDeliveryFailedException()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public EventDeliveryFailedException(String message)
|
||||
: base(message)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public EventDeliveryFailedException(String message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private EventDeliveryFailedException(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
internal sealed class WorkflowMessageEventHandler
|
||||
{
|
||||
Type proxiedType;
|
||||
string eventName;
|
||||
[NonSerialized]
|
||||
Type eventHandlerType;
|
||||
[NonSerialized]
|
||||
IDeliverMessage enqueueWrapper;
|
||||
|
||||
internal WorkflowMessageEventHandler(Type proxiedType, EventInfo eventInfo, IDeliverMessage enqueueWrapper)
|
||||
{
|
||||
this.proxiedType = proxiedType;
|
||||
this.eventName = eventInfo.Name;
|
||||
this.eventHandlerType = eventInfo.EventHandlerType;
|
||||
this.enqueueWrapper = enqueueWrapper;
|
||||
}
|
||||
|
||||
internal IDeliverMessage EnqueueWrapper
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.enqueueWrapper;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentNullException("value");
|
||||
}
|
||||
this.enqueueWrapper = value;
|
||||
}
|
||||
}
|
||||
|
||||
internal Delegate Delegate
|
||||
{
|
||||
get
|
||||
{
|
||||
MethodInfo interceptedHandler = this.eventHandlerType.GetMethod("Invoke");
|
||||
ParameterInfo[] parameters = interceptedHandler.GetParameters();
|
||||
bool isValidParameter = false;
|
||||
if (parameters.Length == 2)
|
||||
{
|
||||
if (parameters[1].ParameterType.IsSubclassOf(typeof(ExternalDataEventArgs))
|
||||
|| parameters[1].ParameterType == (typeof(ExternalDataEventArgs)))
|
||||
isValidParameter = true;
|
||||
}
|
||||
|
||||
if (isValidParameter)
|
||||
{
|
||||
MethodInfo mHandler = typeof(WorkflowMessageEventHandler).GetMethod("EventHandler");
|
||||
return (Delegate)Activator.CreateInstance(eventHandlerType, new object[] { this, mHandler.MethodHandle.GetFunctionPointer() });
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void EventHandler(object sender, ExternalDataEventArgs eventArgs)
|
||||
{
|
||||
if (eventArgs == null)
|
||||
{
|
||||
throw new ArgumentNullException("eventArgs");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
object workItem;
|
||||
IPendingWork workHandler;
|
||||
object[] args = this.enqueueWrapper.PrepareEventArgsArray(sender, eventArgs, out workItem, out workHandler);
|
||||
EventQueueName key = GetKey(args);
|
||||
|
||||
String securityIdentifier = null;
|
||||
if (eventArgs.Identity == null)
|
||||
{
|
||||
IIdentity identity = System.Threading.Thread.CurrentPrincipal.Identity;
|
||||
WindowsIdentity windowsIdentity = identity as WindowsIdentity;
|
||||
if (windowsIdentity != null && windowsIdentity.User != null)
|
||||
securityIdentifier = windowsIdentity.User.Translate(typeof(NTAccount)).ToString();
|
||||
else if (identity != null)
|
||||
securityIdentifier = identity.Name;
|
||||
|
||||
eventArgs.Identity = securityIdentifier;
|
||||
}
|
||||
else
|
||||
{
|
||||
securityIdentifier = eventArgs.Identity;
|
||||
}
|
||||
|
||||
MethodMessage message = new MethodMessage(this.proxiedType, this.eventName, args, securityIdentifier);
|
||||
|
||||
WorkflowActivityTrace.Activity.TraceEvent(TraceEventType.Information, 0, "Firing event {0} for instance {1}", this.eventName, eventArgs.InstanceId);
|
||||
|
||||
this.enqueueWrapper.DeliverMessage(eventArgs, key, message, workItem, workHandler);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (ExternalDataExchangeService.IsIrrecoverableException(e))
|
||||
{
|
||||
throw;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new EventDeliveryFailedException(SR.GetString(SR.Error_EventDeliveryFailedException, this.proxiedType, this.eventName, eventArgs.InstanceId), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private EventQueueName GetKey(object[] eventArgs)
|
||||
{
|
||||
bool provideInitializerTokens = CorrelationResolver.IsInitializingMember(this.proxiedType, this.eventName, eventArgs);
|
||||
|
||||
ICollection<CorrelationProperty> predicates = CorrelationResolver.ResolveCorrelationValues(this.proxiedType, this.eventName, eventArgs, provideInitializerTokens);
|
||||
return new EventQueueName(this.proxiedType, this.eventName, predicates);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user