Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WF / Activities / LocalService / CorrelationResolver.cs / 1305376 / CorrelationResolver.cs
//------------------------------------------------------------
// 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 cachedTypeResolver = new Dictionary();
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 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 cachedCorrelationProperties;
object cachedCorrelationPropertiesSync = new object();
// cached initializers
// map operation to bool flag to indicate events
Dictionary initializerCorrelationPropertys = null;
object initializerCorrelationPropertysSync = new object();
internal DefaultCorrelationProvider(Type interfaceType)
{
this.cachedCorrelationProperties = new Dictionary();
this.interfaceType = interfaceType;
}
ICollection 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 predicates = new List();
for (int i = 0; i < correlationProperties.Length; i++)
{
predicates.Add(new CorrelationProperty(correlationProperties[i].Name,correlationProperties[i].GetValue(methodArgs)));
}
return predicates;
}
private Dictionary InitializerCorrelationPropertys
{
get
{
if (this.initializerCorrelationPropertys == null)
{
lock (this.initializerCorrelationPropertysSync)
{
if (this.initializerCorrelationPropertys == null)
{
Dictionary members = new Dictionary();
// 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