| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013 |
- //-----------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace System.ServiceModel.Description
- {
- using System.Collections.Generic;
- using System.Globalization;
- using System.Reflection;
- using System.Runtime;
- using System.ServiceModel;
- using System.Xml;
- using System.Threading.Tasks;
- using System.Threading;
- static class NamingHelper
- {
- internal const string DefaultNamespace = "http://tempuri.org/";
- internal const string DefaultServiceName = "service";
- internal const string MSNamespace = "http://schemas.microsoft.com/2005/07/ServiceModel";
- // simplified rules for appending paths to base URIs. note that this differs from new Uri(baseUri, string)
- // 1) CombineUriStrings("http://foo/bar/z", "baz") ==> "http://foo/bar/z/baz"
- // 2) CombineUriStrings("http://foo/bar/z/", "baz") ==> "http://foo/bar/z/baz"
- // 3) CombineUriStrings("http://foo/bar/z", "/baz") ==> "http://foo/bar/z/baz"
- // 4) CombineUriStrings("http://foo/bar/z", "http://baz/q") ==> "http://baz/q"
- // 5) CombineUriStrings("http://foo/bar/z", "") ==> ""
- internal static string CombineUriStrings(string baseUri, string path)
- {
- if (Uri.IsWellFormedUriString(path, UriKind.Absolute) || path == String.Empty)
- {
- return path;
- }
- else
- {
- // combine
- if (baseUri.EndsWith("/", StringComparison.Ordinal))
- {
- return baseUri + (path.StartsWith("/", StringComparison.Ordinal) ? path.Substring(1) : path);
- }
- else
- {
- return baseUri + (path.StartsWith("/", StringComparison.Ordinal) ? path : "/" + path);
- }
- }
- }
- internal static string TypeName(Type t)
- {
- if (t.IsGenericType || t.ContainsGenericParameters)
- {
- Type[] args = t.GetGenericArguments();
- int nameEnd = t.Name.IndexOf('`');
- string result = nameEnd > 0 ? t.Name.Substring(0, nameEnd) : t.Name;
- result += "Of";
- for (int i = 0; i < args.Length; ++i)
- {
- result = result + "_" + TypeName(args[i]);
- }
- return result;
- }
- else if (t.IsArray)
- {
- return "ArrayOf" + TypeName(t.GetElementType());
- }
- else
- {
- return t.Name;
- }
- }
- // name, ns could have any combination of nulls
- internal static XmlQualifiedName GetContractName(Type contractType, string name, string ns)
- {
- XmlName xmlName = new XmlName(name ?? TypeName(contractType));
- // ns can be empty
- if (ns == null)
- {
- ns = DefaultNamespace;
- }
- return new XmlQualifiedName(xmlName.EncodedName, ns);
- }
- // name could be null
- // logicalMethodName is MethodInfo.Name with Begin removed for async pattern
- // return encoded version to be used in OperationDescription
- internal static XmlName GetOperationName(string logicalMethodName, string name)
- {
- return new XmlName(String.IsNullOrEmpty(name) ? logicalMethodName : name);
- }
- internal static string GetMessageAction(OperationDescription operation, bool isResponse)
- {
- ContractDescription contract = operation.DeclaringContract;
- XmlQualifiedName contractQname = new XmlQualifiedName(contract.Name, contract.Namespace);
- return GetMessageAction(contractQname, operation.CodeName, null, isResponse);
- }
- // name could be null
- // logicalMethodName is MethodInfo.Name with Begin removed for async pattern
- internal static string GetMessageAction(XmlQualifiedName contractName, string opname, string action, bool isResponse)
- {
- if (action != null)
- {
- return action;
- }
- System.Text.StringBuilder actionBuilder = new System.Text.StringBuilder(64);
- if (String.IsNullOrEmpty(contractName.Namespace))
- {
- actionBuilder.Append("urn:");
- }
- else
- {
- actionBuilder.Append(contractName.Namespace);
- if (!contractName.Namespace.EndsWith("/", StringComparison.Ordinal))
- {
- actionBuilder.Append('/');
- }
- }
- actionBuilder.Append(contractName.Name);
- actionBuilder.Append('/');
- action = isResponse ? opname + "Response" : opname;
- return CombineUriStrings(actionBuilder.ToString(), action);
- }
- internal delegate bool DoesNameExist(string name, object nameCollection);
- internal static string GetUniqueName(string baseName, DoesNameExist doesNameExist, object nameCollection)
- {
- for (int i = 0; i < Int32.MaxValue; i++)
- {
- string name = i > 0 ? baseName + i : baseName;
- if (!doesNameExist(name, nameCollection))
- {
- return name;
- }
- }
- Fx.Assert("Too Many Names");
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Cannot generate unique name for name {0}", baseName)));
- }
- internal static void CheckUriProperty(string ns, string propName)
- {
- Uri uri;
- if (!Uri.TryCreate(ns, UriKind.RelativeOrAbsolute, out uri))
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.SFXUnvalidNamespaceValue, ns, propName));
- }
- internal static void CheckUriParameter(string ns, string paramName)
- {
- Uri uri;
- if (!Uri.TryCreate(ns, UriKind.RelativeOrAbsolute, out uri))
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(paramName, SR.GetString(SR.SFXUnvalidNamespaceParam, ns));
- }
- // Converts names that contain characters that are not permitted in XML names to valid names.
- internal static string XmlName(string name)
- {
- if (string.IsNullOrEmpty(name))
- return name;
- if (IsAsciiLocalName(name))
- return name;
- if (IsValidNCName(name))
- return name;
- return XmlConvert.EncodeLocalName(name);
- }
- // Transforms an XML name into an object name.
- internal static string CodeName(string name)
- {
- return XmlConvert.DecodeName(name);
- }
- static bool IsAlpha(char ch)
- {
- return (ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z');
- }
- static bool IsDigit(char ch)
- {
- return (ch >= '0' && ch <= '9');
- }
- static bool IsAsciiLocalName(string localName)
- {
- Fx.Assert(null != localName, "");
- if (!IsAlpha(localName[0]))
- return false;
- for (int i = 1; i < localName.Length; i++)
- {
- char ch = localName[i];
- if (!IsAlpha(ch) && !IsDigit(ch))
- return false;
- }
- return true;
- }
- internal static bool IsValidNCName(string name)
- {
- try
- {
- XmlConvert.VerifyNCName(name);
- return true;
- }
- catch (XmlException)
- {
- return false;
- }
- }
- }
- internal class XmlName
- {
- string decoded;
- string encoded;
- internal XmlName(string name)
- : this(name, false)
- {
- }
- internal XmlName(string name, bool isEncoded)
- {
- if (isEncoded)
- {
- ValidateEncodedName(name, true /*allowNull*/);
- encoded = name;
- }
- else
- {
- decoded = name;
- }
- }
- internal string EncodedName
- {
- get
- {
- if (encoded == null)
- encoded = NamingHelper.XmlName(decoded);
- return encoded;
- }
- }
- internal string DecodedName
- {
- get
- {
- if (decoded == null)
- decoded = NamingHelper.CodeName(encoded);
- return decoded;
- }
- }
- static void ValidateEncodedName(string name, bool allowNull)
- {
- if (allowNull && name == null)
- return;
- try
- {
- XmlConvert.VerifyNCName(name);
- }
- catch (XmlException e)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(e.Message, "name"));
- }
- }
- bool IsEmpty { get { return string.IsNullOrEmpty(encoded) && string.IsNullOrEmpty(decoded); } }
- internal static bool IsNullOrEmpty(XmlName xmlName)
- {
- return xmlName == null || xmlName.IsEmpty;
- }
- bool Matches(XmlName xmlName)
- {
- return string.Equals(this.EncodedName, xmlName.EncodedName, StringComparison.Ordinal);
- }
- public override bool Equals(object obj)
- {
- if (object.ReferenceEquals(obj, this))
- {
- return true;
- }
- if (object.ReferenceEquals(obj, null))
- {
- return false;
- }
- XmlName xmlName = obj as XmlName;
- if (xmlName == null)
- {
- return false;
- }
- return Matches(xmlName);
- }
- public override int GetHashCode()
- {
- if (string.IsNullOrEmpty(EncodedName))
- return 0;
- return EncodedName.GetHashCode();
- }
- public override string ToString()
- {
- if (encoded == null && decoded == null)
- return null;
- if (encoded != null)
- return encoded;
- return decoded;
- }
- public static bool operator ==(XmlName a, XmlName b)
- {
- if (object.ReferenceEquals(a, null))
- {
- return object.ReferenceEquals(b, null);
- }
- return (a.Equals(b));
- }
- public static bool operator !=(XmlName a, XmlName b)
- {
- return !(a == b);
- }
- }
- static internal class ServiceReflector
- {
- internal const BindingFlags ServiceModelBindingFlags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance;
- internal const string BeginMethodNamePrefix = "Begin";
- internal const string EndMethodNamePrefix = "End";
- internal static readonly Type VoidType = typeof(void);
- internal const string AsyncMethodNameSuffix = "Async";
- internal static readonly Type taskType = typeof(Task);
- internal static readonly Type taskTResultType = typeof(Task<>);
- internal static readonly Type CancellationTokenType = typeof(CancellationToken);
- internal static readonly Type IProgressType = typeof(IProgress<>);
- static readonly Type asyncCallbackType = typeof(AsyncCallback);
- static readonly Type asyncResultType = typeof(IAsyncResult);
- static readonly Type objectType = typeof(object);
- static readonly Type OperationContractAttributeType = typeof(OperationContractAttribute);
- static internal Type GetOperationContractProviderType(MethodInfo method)
- {
- if (GetSingleAttribute<OperationContractAttribute>(method) != null)
- {
- return OperationContractAttributeType;
- }
- IOperationContractAttributeProvider provider = GetFirstAttribute<IOperationContractAttributeProvider>(method);
- if (provider != null)
- {
- return provider.GetType();
- }
- return null;
- }
- // returns the set of root interfaces for the service class (meaning doesn't include callback ifaces)
- static internal List<Type> GetInterfaces(Type service)
- {
- List<Type> types = new List<Type>();
- bool implicitContract = false;
- if (service.IsDefined(typeof(ServiceContractAttribute), false))
- {
- implicitContract = true;
- types.Add(service);
- }
- if (!implicitContract)
- {
- Type t = GetAncestorImplicitContractClass(service);
- if (t != null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxContractInheritanceRequiresInterfaces2, service, t)));
- }
- foreach (MethodInfo method in GetMethodsInternal(service))
- {
- Type operationContractProviderType = GetOperationContractProviderType(method);
- if (operationContractProviderType == OperationContractAttributeType)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ServicesWithoutAServiceContractAttributeCan2, operationContractProviderType.Name, method.Name, service.FullName)));
- }
- }
- }
- foreach (Type t in service.GetInterfaces())
- {
- if (t.IsDefined(typeof(ServiceContractAttribute), false))
- {
- if (implicitContract)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxContractInheritanceRequiresInterfaces, service, t)));
- }
- types.Add(t);
- }
- }
- return types;
- }
- static Type GetAncestorImplicitContractClass(Type service)
- {
- for (service = service.BaseType; service != null; service = service.BaseType)
- {
- if (ServiceReflector.GetSingleAttribute<ServiceContractAttribute>(service) != null)
- {
- return service;
- }
- }
- return null;
- }
- static internal List<Type> GetInheritedContractTypes(Type service)
- {
- List<Type> types = new List<Type>();
- foreach (Type t in service.GetInterfaces())
- {
- if (ServiceReflector.GetSingleAttribute<ServiceContractAttribute>(t) != null)
- {
- types.Add(t);
- }
- }
- for (service = service.BaseType; service != null; service = service.BaseType)
- {
- if (ServiceReflector.GetSingleAttribute<ServiceContractAttribute>(service) != null)
- {
- types.Add(service);
- }
- }
- return types;
- }
- static internal object[] GetCustomAttributes(ICustomAttributeProvider attrProvider, Type attrType)
- {
- return GetCustomAttributes(attrProvider, attrType, false);
- }
- static internal object[] GetCustomAttributes(ICustomAttributeProvider attrProvider, Type attrType, bool inherit)
- {
- try
- {
- return attrProvider.GetCustomAttributes(attrType, inherit);
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- // where the exception is CustomAttributeFormatException and the InnerException is a TargetInvocationException,
- // drill into the InnerException as this will provide a better error experience (fewer nested InnerExceptions)
- if (e is CustomAttributeFormatException && e.InnerException != null)
- {
- e = e.InnerException;
- if (e is TargetInvocationException && e.InnerException != null)
- {
- e = e.InnerException;
- }
- }
- Type type = attrProvider as Type;
- MethodInfo method = attrProvider as MethodInfo;
- ParameterInfo param = attrProvider as ParameterInfo;
- // there is no good way to know if this is a return type attribute
- if (type != null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
- SR.GetString(SR.SFxErrorReflectingOnType2, attrType.Name, type.Name), e));
- }
- else if (method != null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
- SR.GetString(SR.SFxErrorReflectingOnMethod3,
- attrType.Name, method.Name, method.ReflectedType.Name), e));
- }
- else if (param != null)
- {
- method = param.Member as MethodInfo;
- if (method != null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
- SR.GetString(SR.SFxErrorReflectingOnParameter4,
- attrType.Name, param.Name, method.Name, method.ReflectedType.Name), e));
- }
- }
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
- SR.GetString(SR.SFxErrorReflectionOnUnknown1, attrType.Name), e));
- }
- }
- static internal T GetFirstAttribute<T>(ICustomAttributeProvider attrProvider)
- where T : class
- {
- Type attrType = typeof(T);
- object[] attrs = GetCustomAttributes(attrProvider, attrType);
- if (attrs.Length == 0)
- {
- return null;
- }
- else
- {
- return attrs[0] as T;
- }
- }
- #if !NO_GENERIC
- static internal T GetSingleAttribute<T>(ICustomAttributeProvider attrProvider)
- where T : class
- {
- Type attrType = typeof(T);
- object[] attrs = GetCustomAttributes(attrProvider, attrType);
- if (attrs.Length == 0)
- {
- return null;
- }
- else if (attrs.Length > 1)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.tooManyAttributesOfTypeOn2, attrType, attrProvider.ToString())));
- }
- else
- {
- return attrs[0] as T;
- }
- }
- #else
- static internal object GetSingleAttribute(Type attrType, ICustomAttributeProvider attrProvider)
- {
- object[] attrs = GetCustomAttributes(attrProvider, attrType);
- if (attrs.Length == 0)
- {
- return null;
- }
- else if (attrs.Length > 1)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.tooManyAttributesOfTypeOn2, attrType, attrProvider.ToString())));
- }
- else
- {
- return attrs[0];
- }
- }
- #endif
- #if !NO_GENERIC
- static internal T GetRequiredSingleAttribute<T>(ICustomAttributeProvider attrProvider)
- where T : class
- {
- T result = GetSingleAttribute<T>(attrProvider);
- if (result == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.couldnTFindRequiredAttributeOfTypeOn2, typeof(T), attrProvider.ToString())));
- }
- return result;
- }
- #else
- static internal object GetRequiredSingleAttribute(Type attrType, ICustomAttributeProvider attrProvider)
- {
- object result = GetSingleAttribute(attrType, attrProvider);
- if (result == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.couldnTFindRequiredAttributeOfTypeOn2, attrType, attrProvider.ToString())));
- }
- return result;
- }
- #endif
- #if !NO_GENERIC
- static internal T GetSingleAttribute<T>(ICustomAttributeProvider attrProvider, Type[] attrTypeGroup)
- where T : class
- {
- T result = GetSingleAttribute<T>(attrProvider);
- if (result != null)
- {
- Type attrType = typeof(T);
- foreach (Type otherType in attrTypeGroup)
- {
- if (otherType == attrType)
- {
- continue;
- }
- object[] attrs = GetCustomAttributes(attrProvider, otherType);
- if (attrs != null && attrs.Length > 0)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxDisallowedAttributeCombination, attrProvider, attrType.FullName, otherType.FullName)));
- }
- }
- }
- return result;
- }
- #else
- static internal object GetSingleAttribute(Type attrType, ICustomAttributeProvider attrProvider, Type[] attrTypeGroup)
- {
- object result = GetSingleAttribute(attrType, attrProvider);
- if (result != null)
- {
- foreach (Type otherType in attrTypeGroup)
- {
- if (otherType == attrType)
- {
- continue;
- }
- object[] attrs = GetCustomAttributes(attrProvider, otherType);
- if (attrs != null && attrs.Length > 0)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxDisallowedAttributeCombination, attrProvider, attrType.FullName, otherType.FullName)));
- }
- }
- }
- return result;
- }
- #endif
- #if !NO_GENERIC
- static internal T GetRequiredSingleAttribute<T>(ICustomAttributeProvider attrProvider, Type[] attrTypeGroup)
- where T : class
- {
- T result = GetSingleAttribute<T>(attrProvider, attrTypeGroup);
- if (result == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.couldnTFindRequiredAttributeOfTypeOn2, typeof(T), attrProvider.ToString())));
- }
- return result;
- }
- #else
- static internal object GetRequiredSingleAttribute(Type attrType, ICustomAttributeProvider attrProvider, Type[] attrTypeGroup)
- {
- object result = GetSingleAttribute(attrType, attrProvider, attrTypeGroup);
- if (result == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.couldnTFindRequiredAttributeOfTypeOn2, attrType, attrProvider.ToString())));
- }
- return result;
- }
- #endif
- static internal Type GetContractType(Type interfaceType)
- {
- ServiceContractAttribute contractAttribute;
- return GetContractTypeAndAttribute(interfaceType, out contractAttribute);
- }
- static internal Type GetContractTypeAndAttribute(Type interfaceType, out ServiceContractAttribute contractAttribute)
- {
- contractAttribute = GetSingleAttribute<ServiceContractAttribute>(interfaceType);
- if (contractAttribute != null)
- {
- return interfaceType;
- }
- List<Type> types = new List<Type>(GetInheritedContractTypes(interfaceType));
- if (types.Count == 0)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.AttemptedToGetContractTypeForButThatTypeIs1, interfaceType.Name)));
- }
- foreach (Type potentialContractRoot in types)
- {
- bool mayBeTheRoot = true;
- foreach (Type t in types)
- {
- if (!t.IsAssignableFrom(potentialContractRoot))
- {
- mayBeTheRoot = false;
- }
- }
- if (mayBeTheRoot)
- {
- contractAttribute = GetSingleAttribute<ServiceContractAttribute>(potentialContractRoot);
- return potentialContractRoot;
- }
- }
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
- SR.GetString(SR.SFxNoMostDerivedContract, interfaceType.Name)));
- }
- static List<MethodInfo> GetMethodsInternal(Type interfaceType)
- {
- List<MethodInfo> methods = new List<MethodInfo>();
- foreach (MethodInfo mi in interfaceType.GetMethods(ServiceModelBindingFlags))
- {
- if (GetSingleAttribute<OperationContractAttribute>(mi) != null)
- {
- methods.Add(mi);
- }
- else if (GetFirstAttribute<IOperationContractAttributeProvider>(mi) != null)
- {
- methods.Add(mi);
- }
- }
- return methods;
- }
- // The metadata for "in" versus "out" seems to be inconsistent, depending upon what compiler generates it.
- // The following code assumes this is the truth table that all compilers will obey:
- //
- // True Parameter Type .IsIn .IsOut .ParameterType.IsByRef
- //
- // in F F F ...OR...
- // in T F F
- //
- // in/out T T T ...OR...
- // in/out F F T
- //
- // out F T T
- static internal void ValidateParameterMetadata(MethodInfo methodInfo)
- {
- ParameterInfo[] parameters = methodInfo.GetParameters();
- foreach (ParameterInfo parameter in parameters)
- {
- if (!parameter.ParameterType.IsByRef)
- {
- if (parameter.IsOut)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new InvalidOperationException(SR.GetString(SR.SFxBadByValueParameterMetadata,
- methodInfo.Name, methodInfo.DeclaringType.Name)));
- }
- }
- else
- {
- if (parameter.IsIn && !parameter.IsOut)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new InvalidOperationException(SR.GetString(SR.SFxBadByReferenceParameterMetadata,
- methodInfo.Name, methodInfo.DeclaringType.Name)));
- }
- }
- }
- }
- static internal bool FlowsIn(ParameterInfo paramInfo) // conceptually both "in" and "in/out" params return true
- {
- return !paramInfo.IsOut || paramInfo.IsIn;
- }
- static internal bool FlowsOut(ParameterInfo paramInfo) // conceptually both "out" and "in/out" params return true
- {
- return paramInfo.ParameterType.IsByRef;
- }
- // for async method is the begin method
- static internal ParameterInfo[] GetInputParameters(MethodInfo method, bool asyncPattern)
- {
- int count = 0;
- ParameterInfo[] parameters = method.GetParameters();
- // length of parameters we care about (-2 for async)
- int len = parameters.Length;
- if (asyncPattern)
- {
- len -= 2;
- }
- // count the ins
- for (int i = 0; i < len; i++)
- {
- if (FlowsIn(parameters[i]))
- {
- count++;
- }
- }
- // grab the ins
- ParameterInfo[] result = new ParameterInfo[count];
- int pos = 0;
- for (int i = 0; i < len; i++)
- {
- ParameterInfo param = parameters[i];
- if (FlowsIn(param))
- {
- result[pos++] = param;
- }
- }
- return result;
- }
- // for async method is the end method
- static internal ParameterInfo[] GetOutputParameters(MethodInfo method, bool asyncPattern)
- {
- int count = 0;
- ParameterInfo[] parameters = method.GetParameters();
- // length of parameters we care about (-1 for async)
- int len = parameters.Length;
- if (asyncPattern)
- {
- len -= 1;
- }
- // count the outs
- for (int i = 0; i < len; i++)
- {
- if (FlowsOut(parameters[i]))
- {
- count++;
- }
- }
- // grab the outs
- ParameterInfo[] result = new ParameterInfo[count];
- int pos = 0;
- for (int i = 0; i < len; i++)
- {
- ParameterInfo param = parameters[i];
- if (FlowsOut(param))
- {
- result[pos++] = param;
- }
- }
- return result;
- }
- static internal bool HasOutputParameters(MethodInfo method, bool asyncPattern)
- {
- ParameterInfo[] parameters = method.GetParameters();
- // length of parameters we care about (-1 for async)
- int len = parameters.Length;
- if (asyncPattern)
- {
- len -= 1;
- }
- // count the outs
- for (int i = 0; i < len; i++)
- {
- if (FlowsOut(parameters[i]))
- {
- return true;
- }
- }
- return false;
- }
- static MethodInfo GetEndMethodInternal(MethodInfo beginMethod)
- {
- string logicalName = GetLogicalName(beginMethod);
- string endMethodName = EndMethodNamePrefix + logicalName;
- MemberInfo[] endMethods = beginMethod.DeclaringType.GetMember(endMethodName, ServiceModelBindingFlags);
- if (endMethods.Length == 0)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.NoEndMethodFoundForAsyncBeginMethod3, beginMethod.Name, beginMethod.DeclaringType.FullName, endMethodName)));
- }
- if (endMethods.Length > 1)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MoreThanOneEndMethodFoundForAsyncBeginMethod3, beginMethod.Name, beginMethod.DeclaringType.FullName, endMethodName)));
- }
- return (MethodInfo)endMethods[0];
- }
- static internal MethodInfo GetEndMethod(MethodInfo beginMethod)
- {
- MethodInfo endMethod = GetEndMethodInternal(beginMethod);
- if (!HasEndMethodShape(endMethod))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.InvalidAsyncEndMethodSignatureForMethod2, endMethod.Name, endMethod.DeclaringType.FullName)));
- }
- return endMethod;
- }
- static internal XmlName GetOperationName(MethodInfo method)
- {
- OperationContractAttribute operationAttribute = GetOperationContractAttribute(method);
- return NamingHelper.GetOperationName(GetLogicalName(method), operationAttribute.Name);
- }
- static internal bool HasBeginMethodShape(MethodInfo method)
- {
- ParameterInfo[] parameters = method.GetParameters();
- if (!method.Name.StartsWith(BeginMethodNamePrefix, StringComparison.Ordinal) ||
- parameters.Length < 2 ||
- parameters[parameters.Length - 2].ParameterType != asyncCallbackType ||
- parameters[parameters.Length - 1].ParameterType != objectType ||
- method.ReturnType != asyncResultType)
- {
- return false;
- }
- return true;
- }
- static internal bool IsBegin(OperationContractAttribute opSettings, MethodInfo method)
- {
- if (opSettings.AsyncPattern)
- {
- if (!HasBeginMethodShape(method))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.InvalidAsyncBeginMethodSignatureForMethod2, method.Name, method.DeclaringType.FullName)));
- }
- return true;
- }
- return false;
- }
- static internal bool IsTask(MethodInfo method)
- {
- if (method.ReturnType == taskType)
- {
- return true;
- }
- if (method.ReturnType.IsGenericType && method.ReturnType.GetGenericTypeDefinition() == taskTResultType)
- {
- return true;
- }
- return false;
- }
- static internal bool IsTask(MethodInfo method, out Type taskTResult)
- {
- taskTResult = null;
- Type methodReturnType = method.ReturnType;
- if (methodReturnType == taskType)
- {
- taskTResult = VoidType;
- return true;
- }
- if (methodReturnType.IsGenericType && methodReturnType.GetGenericTypeDefinition() == taskTResultType)
- {
- taskTResult = methodReturnType.GetGenericArguments()[0];
- return true;
- }
- return false;
- }
- static internal bool HasEndMethodShape(MethodInfo method)
- {
- ParameterInfo[] parameters = method.GetParameters();
- if (!method.Name.StartsWith(EndMethodNamePrefix, StringComparison.Ordinal) ||
- parameters.Length < 1 ||
- parameters[parameters.Length - 1].ParameterType != asyncResultType)
- {
- return false;
- }
- return true;
- }
- internal static OperationContractAttribute GetOperationContractAttribute(MethodInfo method)
- {
- OperationContractAttribute operationContractAttribute = GetSingleAttribute<OperationContractAttribute>(method);
- if (operationContractAttribute != null)
- {
- return operationContractAttribute;
- }
- IOperationContractAttributeProvider operationContractProvider = GetFirstAttribute<IOperationContractAttributeProvider>(method);
- if (operationContractProvider != null)
- {
- return operationContractProvider.GetOperationContractAttribute();
- }
- return null;
- }
- static internal bool IsBegin(MethodInfo method)
- {
- OperationContractAttribute opSettings = GetOperationContractAttribute(method);
- if (opSettings == null)
- return false;
- return IsBegin(opSettings, method);
- }
- static internal string GetLogicalName(MethodInfo method)
- {
- bool isAsync = IsBegin(method);
- bool isTask = isAsync ? false : IsTask(method);
- return GetLogicalName(method, isAsync, isTask);
- }
- static internal string GetLogicalName(MethodInfo method, bool isAsync, bool isTask)
- {
- if (isAsync)
- {
- return method.Name.Substring(BeginMethodNamePrefix.Length);
- }
- else if (isTask && method.Name.EndsWith(AsyncMethodNameSuffix, StringComparison.Ordinal))
- {
- return method.Name.Substring(0, method.Name.Length - AsyncMethodNameSuffix.Length);
- }
- else
- {
- return method.Name;
- }
- }
- static internal bool HasNoDisposableParameters(MethodInfo methodInfo)
- {
- foreach (ParameterInfo inputInfo in methodInfo.GetParameters())
- {
- if (IsParameterDisposable(inputInfo.ParameterType))
- {
- return false;
- }
- }
- if (methodInfo.ReturnParameter != null)
- {
- return (!IsParameterDisposable(methodInfo.ReturnParameter.ParameterType));
- }
- return true;
- }
- static internal bool IsParameterDisposable(Type type)
- {
- return ((!type.IsSealed) || typeof(IDisposable).IsAssignableFrom(type));
- }
- }
- }
|