//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------ namespace System.Workflow.Activities { using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Reflection; using System.Runtime; using System.ServiceModel; using System.ServiceModel.Description; using System.Workflow.ComponentModel; using System.Workflow.ComponentModel.Compiler; internal static class ServiceOperationHelpers { public static string GetOperationName(IServiceProvider serviceProvider, MethodInfo methodInfo) { Fx.Assert((methodInfo != null), " MethoInfo cannot be null"); string operationName = methodInfo.Name; object[] operationContractAttribs = methodInfo.GetCustomAttributes(typeof(OperationContractAttribute), true); if (operationContractAttribs != null && operationContractAttribs.Length > 0) { if (operationContractAttribs[0] is OperationContractAttribute) { OperationContractAttribute operationContractAttribute = operationContractAttribs[0] as OperationContractAttribute; if (!String.IsNullOrEmpty(operationContractAttribute.Name)) { operationName = operationContractAttribute.Name; } } if (operationContractAttribs[0] is AttributeInfoAttribute) { AttributeInfoAttribute attribInfoAttrib = operationContractAttribs[0] as AttributeInfoAttribute; string propertyName = "Name"; string namePropertyValue; if (TryGetArgumentValueAs(serviceProvider, attribInfoAttrib.AttributeInfo, propertyName, out namePropertyValue)) { operationName = namePropertyValue; } } } return operationName; } public static PropertyDescriptor GetServiceOperationInfoPropertyDescriptor(Activity activity) { if (activity is ReceiveActivity) { return TypeDescriptor.GetProperties(activity)[ReceiveActivity.ServiceOperationInfoProperty.Name]; } else { Fx.Assert(activity is SendActivity, " only Receive and Send activities are valid inputs to this method"); return TypeDescriptor.GetProperties(activity)[SendActivity.ServiceOperationInfoProperty.Name]; } } public static bool IsAsyncOperation(IServiceProvider serviceProvider, MethodInfo methodInfo) { if (serviceProvider == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serviceProvider"); } if (methodInfo == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("methodInfo"); } bool isAsync = false; object[] operationContractAttribs = methodInfo.GetCustomAttributes(typeof(OperationContractAttribute), true); Fx.Assert(operationContractAttribs != null, "returned attribs list cannot be null"); Fx.Assert(operationContractAttribs.Length > 0, "operation doesnt seem to be a valid operationcontract"); if (operationContractAttribs[0] is OperationContractAttribute) { OperationContractAttribute operationContractAttribute = operationContractAttribs[0] as OperationContractAttribute; isAsync = operationContractAttribute.AsyncPattern; } if (operationContractAttribs[0] is AttributeInfoAttribute) { AttributeInfoAttribute attribInfoAttrib = operationContractAttribs[0] as AttributeInfoAttribute; isAsync = GetOperationAsyncPattern(serviceProvider, attribInfoAttrib.AttributeInfo); } return isAsync; } public static bool IsInitiatingOperation(IServiceProvider serviceProvider, MethodInfo methodInfo) { if (serviceProvider == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serviceProvider"); } if (methodInfo == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("methodInfo"); } bool isInitiating = true; object[] operationContractAttribs = methodInfo.GetCustomAttributes(typeof(OperationContractAttribute), true); Fx.Assert(operationContractAttribs != null, "returned attribs list cannot be null"); Fx.Assert(operationContractAttribs.Length > 0, "operation doesnt seem to be a valid operationcontract"); if (operationContractAttribs[0] is OperationContractAttribute) { OperationContractAttribute operationContractAttribute = operationContractAttribs[0] as OperationContractAttribute; isInitiating = operationContractAttribute.IsInitiating; } if (operationContractAttribs[0] is AttributeInfoAttribute) { AttributeInfoAttribute attribInfoAttrib = operationContractAttribs[0] as AttributeInfoAttribute; isInitiating = IsInitiatingOperationContract(serviceProvider, attribInfoAttrib.AttributeInfo); } return isInitiating; } public static bool IsNullableType(Type type) { return (Nullable.GetUnderlyingType(type.IsByRef ? type.GetElementType() : type) != null); } public static bool IsValidServiceContract(Type contractType) { if (contractType == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contractType"); } object[] contractAttribs = contractType.GetCustomAttributes(typeof(ServiceContractAttribute), false); if (contractAttribs != null && contractAttribs.Length > 0) { if (contractAttribs[0] is ServiceContractAttribute) { return true; } if (contractAttribs[0] is AttributeInfoAttribute) { AttributeInfoAttribute attribInfoAttrib = contractAttribs[0] as AttributeInfoAttribute; if (typeof(ServiceContractAttribute).IsAssignableFrom(attribInfoAttrib.AttributeInfo.AttributeType)) { return true; } } } return false; } public static bool IsValidServiceOperation(MethodInfo methodInfo) { if (methodInfo == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("methodInfo"); } object[] operationContractAttribs = methodInfo.GetCustomAttributes(typeof(OperationContractAttribute), true); if (operationContractAttribs != null && operationContractAttribs.Length > 0) { if (operationContractAttribs[0] is OperationContractAttribute) { return true; } if (operationContractAttribs[0] is AttributeInfoAttribute) { AttributeInfoAttribute attribInfoAttrib = operationContractAttribs[0] as AttributeInfoAttribute; if (typeof(OperationContractAttribute).IsAssignableFrom(attribInfoAttrib.AttributeInfo.AttributeType)) { return true; } } } return false; } internal static List GetContracts(Type contractType) { List types = new List(); if (contractType.IsDefined(typeof(ServiceContractAttribute), false)) { types.Add(contractType); } foreach (Type contract in contractType.GetInterfaces()) { if (contract.IsDefined(typeof(ServiceContractAttribute), false)) { types.Add(contract); } } return types; } internal static SessionMode GetContractSessionMode(IServiceProvider serviceProvider, AttributeInfo attribInfo) { string propertyName = "SessionMode"; SessionMode sessionMode = SessionMode.Allowed; if (!TryGetArgumentValueAs(serviceProvider, attribInfo, propertyName, out sessionMode)) { sessionMode = SessionMode.Allowed; } return sessionMode; } internal static object[] GetCustomAttributes(Type attributeType, Attribute[] attributes) { if (attributeType == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("attributeType"); } ArrayList attributeList = new ArrayList(); foreach (Attribute currentAttribute in attributes) { if (attributeType.IsAssignableFrom(currentAttribute.GetType())) { attributeList.Add(currentAttribute); } } return attributeList.ToArray(); } internal static bool GetOperationAsyncPattern(IServiceProvider serviceProvider, AttributeInfo attribInfo) { string propertyName = "AsyncPattern"; bool isAsync = false; if (!TryGetArgumentValueAs(serviceProvider, attribInfo, propertyName, out isAsync)) { isAsync = false; } return isAsync; } internal static bool IsDefined(Type attributeType, Attribute[] attributes) { if (attributeType == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("attributeType"); } foreach (Attribute attribute in attributes) { if (attributeType.IsAssignableFrom(attribute.GetType())) { return true; } } return false; } internal static bool IsInitiatingOperationContract(IServiceProvider serviceProvider, AttributeInfo attribInfo) { string propertyName = "IsInitiating"; bool isInitiating = true; if (!TryGetArgumentValueAs(serviceProvider, attribInfo, propertyName, out isInitiating)) { isInitiating = true; } return isInitiating; } internal static void SetWorkflowOperationBehavior(ContractDescription contractDescription, ServiceDescriptionContext context) { if (contractDescription == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contractDescription"); } if (context == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context"); } foreach (OperationDescription opDescription in contractDescription.Operations) { WorkflowOperationBehavior behavior = null; KeyValuePair operationKey = new KeyValuePair(opDescription.DeclaringContract.ContractType, opDescription.Name); if (!context.WorkflowOperationBehaviors.TryGetValue(operationKey, out behavior)) { behavior = new WorkflowOperationBehavior(); context.WorkflowOperationBehaviors.Add(operationKey, behavior); behavior.CanCreateInstance = false; } if (opDescription.Behaviors.Find() != behavior) { opDescription.Behaviors.Remove(typeof(WorkflowOperationBehavior)); opDescription.Behaviors.Add(behavior); } } } private static string[] GetAttributePropertyNames(AttributeInfo attributeInfo) { if (attributeInfo == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("attributeInfo"); } string[] argumentNames = null; BindingFlags bindingFlags = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic; FieldInfo argumentNamesField = typeof(AttributeInfo).GetField("argumentNames", bindingFlags); if (argumentNamesField != null) { argumentNames = argumentNamesField.GetValue(attributeInfo) as string[]; } return argumentNames; } private static bool TryGetArgumentValueAs(IServiceProvider serviceProvider, AttributeInfo attribInfo, string propertyName, out T propertyValue) { string[] argumentNames = GetAttributePropertyNames(attribInfo); int argumentIndex = -1; for (int index = 0; index < argumentNames.Length; index++) { // skip unnamed arguments these are constructor arguments if (string.IsNullOrEmpty((argumentNames[index]))) { continue; } else { if (argumentNames[index].Equals(propertyName)) { argumentIndex = index; break; } } } if (argumentIndex == -1) { propertyValue = default(T); return false; } propertyValue = (T) attribInfo.GetArgumentValueAs(serviceProvider, argumentIndex, typeof(T)); return true; } } }