using System; using System.Reflection; using System.Drawing; using System.Drawing.Design; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; using System.ComponentModel.Design; using System.Workflow.ComponentModel; using System.Workflow.ComponentModel.Design; using System.Workflow.ComponentModel.Compiler; using System.Workflow.Runtime; using System.CodeDom; using System.ComponentModel.Design.Serialization; using System.Diagnostics; using System.Workflow.Runtime.Hosting; using System.Runtime.Remoting.Messaging; using System.Diagnostics.CodeAnalysis; using System.Workflow.Activities.Common; namespace System.Workflow.Activities { [SRDescription(SR.WebServiceReceiveActivityDescription)] [SRCategory(SR.Standard)] [ToolboxBitmap(typeof(WebServiceInputActivity), "Resources.WebServiceIn.png")] [Designer(typeof(WebServiceReceiveDesigner), typeof(IDesigner))] [ActivityValidator(typeof(WebServiceReceiveValidator))] [ActivityCodeGeneratorAttribute(typeof(WebServiceCodeGenerator))] [DefaultEvent("InputReceived")] [Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")] public sealed class WebServiceInputActivity : Activity, IEventActivity, IPropertyValueProvider, IActivityEventListener, IDynamicPropertyTypeProvider { //metadata properties public static readonly DependencyProperty IsActivatingProperty = DependencyProperty.Register("IsActivating", typeof(bool), typeof(WebServiceInputActivity), new PropertyMetadata(false, DependencyPropertyOptions.Metadata)); public static readonly DependencyProperty InterfaceTypeProperty = DependencyProperty.Register("InterfaceType", typeof(Type), typeof(WebServiceInputActivity), new PropertyMetadata(null, DependencyPropertyOptions.Metadata)); public static readonly DependencyProperty MethodNameProperty = DependencyProperty.Register("MethodName", typeof(string), typeof(WebServiceInputActivity), new PropertyMetadata("", DependencyPropertyOptions.Metadata)); public static readonly DependencyProperty RolesProperty = DependencyProperty.Register("Roles", typeof(WorkflowRoleCollection), typeof(WebServiceInputActivity)); //instance properties public static readonly DependencyProperty ParameterBindingsProperty = DependencyProperty.Register("ParameterBindings", typeof(WorkflowParameterBindingCollection), typeof(WebServiceInputActivity), new PropertyMetadata(DependencyPropertyOptions.Metadata | DependencyPropertyOptions.ReadOnly, new Attribute[] { new BrowsableAttribute(false), new DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Content) })); public static readonly DependencyProperty ActivitySubscribedProperty = DependencyProperty.Register("ActivitySubscribed", typeof(bool), typeof(WebServiceInputActivity), new PropertyMetadata(false)); private static readonly DependencyProperty QueueNameProperty = DependencyProperty.Register("QueueName", typeof(IComparable), typeof(WebServiceInputActivity)); //event public static readonly DependencyProperty InputReceivedEvent = DependencyProperty.Register("InputReceived", typeof(EventHandler), typeof(WebServiceInputActivity)); #region Constructors public WebServiceInputActivity() { // base.SetReadOnlyPropertyValue(ParameterBindingsProperty, new WorkflowParameterBindingCollection(this)); } public WebServiceInputActivity(string name) : base(name) { // base.SetReadOnlyPropertyValue(ParameterBindingsProperty, new WorkflowParameterBindingCollection(this)); } #endregion [SRCategory(SR.Activity)] [SRDescription(SR.InterfaceTypeDescription)] [RefreshProperties(RefreshProperties.All)] [Editor(typeof(TypeBrowserEditor), typeof(UITypeEditor))] [TypeFilterProviderAttribute(typeof(InterfaceTypeFilterProvider))] [DefaultValue(null)] public Type InterfaceType { get { return base.GetValue(InterfaceTypeProperty) as Type; } set { base.SetValue(InterfaceTypeProperty, value); } } [SRCategory(SR.Activity)] [SRDescription(SR.WebServiceMethodDescription)] [TypeConverter(typeof(PropertyValueProviderTypeConverter))] [RefreshProperties(RefreshProperties.All)] [MergablePropertyAttribute(false)] [DefaultValue("")] public string MethodName { get { return (string)base.GetValue(MethodNameProperty); } set { base.SetValue(MethodNameProperty, value); } } [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] [Browsable(false)] public WorkflowParameterBindingCollection ParameterBindings { get { return base.GetValue(ParameterBindingsProperty) as WorkflowParameterBindingCollection; } } [SRCategory(SR.Activity)] [SRDescription(SR.RoleDescr)] [Editor(typeof(BindUITypeEditor), typeof(UITypeEditor))] [DefaultValue(null)] public WorkflowRoleCollection Roles { get { return base.GetValue(RolesProperty) as WorkflowRoleCollection; } set { base.SetValue(RolesProperty, value); } } [SRCategory(SR.Activity)] [SRDescription(SR.ActivationDescr)] [DefaultValue(false)] [MergableProperty(false)] public bool IsActivating { get { return (bool)base.GetValue(IsActivatingProperty); } set { base.SetValue(IsActivatingProperty, value); } } [SRDescription(SR.OnAfterReceiveDescr)] [SRCategory(SR.Handlers)] [MergableProperty(false)] public event EventHandler InputReceived { add { base.AddHandler(InputReceivedEvent, value); } remove { base.RemoveHandler(InputReceivedEvent, value); } } internal bool ActivitySubscribed { get { return (bool)base.GetValue(ActivitySubscribedProperty); } set { base.SetValue(ActivitySubscribedProperty, value); } } ICollection IPropertyValueProvider.GetPropertyValues(ITypeDescriptorContext context) { ITypeProvider typeProvider = (ITypeProvider)context.GetService(typeof(ITypeProvider)); if (typeProvider == null) throw new InvalidOperationException(SR.GetString(SR.General_MissingService, typeof(ITypeProvider).FullName)); StringCollection names = new StringCollection(); if (context.PropertyDescriptor.Name == "MethodName") { if (this.InterfaceType != null) { Type type = typeProvider.GetType(this.InterfaceType.AssemblyQualifiedName); if (type != null) { foreach (MethodInfo method in type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public)) { if (!method.IsSpecialName) names.Add(method.Name); } foreach (Type interfaceType in type.GetInterfaces()) { foreach (MethodInfo method in interfaceType.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public)) { names.Add(interfaceType.FullName + "." + method.Name); } } } } } return names; } protected sealed override void Initialize(IServiceProvider provider) { if (provider == null) throw new ArgumentNullException("provider"); if (this.Parent == null) throw new InvalidOperationException(SR.GetString(SR.Error_MustHaveParent)); WorkflowQueuingService queueService = (WorkflowQueuingService)provider.GetService(typeof(WorkflowQueuingService)); //create a static q entry EventQueueName key = new EventQueueName(this.InterfaceType, this.MethodName); this.SetValue(QueueNameProperty, key); if (!queueService.Exists(key)) queueService.CreateWorkflowQueue(key, true); } #region Execute/Cancel protected sealed override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext) { if (executionContext == null) throw new ArgumentNullException("executionContext"); ActivityExecutionStatus status = ExecuteForActivity(executionContext, this.InterfaceType, this.MethodName); if (status == ActivityExecutionStatus.Closed) { UnsubscribeForActivity(executionContext); executionContext.CloseActivity(); return status; } // cannot resolve queue name or message not available // hence subscribe for message arrival if (!this.ActivitySubscribed) { this.ActivitySubscribed = CorrelationService.Subscribe(executionContext, this, this.InterfaceType, this.MethodName, this, this.WorkflowInstanceId); } return ActivityExecutionStatus.Executing; } private ActivityExecutionStatus ExecuteForActivity(ActivityExecutionContext context, Type interfaceType, string operation) { WorkflowQueuingService queueSvcs = (WorkflowQueuingService)context.GetService(typeof(WorkflowQueuingService)); IComparable queueName = new EventQueueName(interfaceType, operation); if (queueName != null) { WorkflowQueue queue; object message = InboundActivityHelper.DequeueMessage(queueName, queueSvcs, this, out queue); if (message != null) { ProcessMessage(context, message, interfaceType, operation); return ActivityExecutionStatus.Closed; } } return ActivityExecutionStatus.Executing; } private void ProcessMessage(ActivityExecutionContext context, object msg, Type interfaceType, string operation) { IMethodMessage message = msg as IMethodMessage; if (message == null) { Exception excp = msg as Exception; if (excp != null) throw excp; throw new ArgumentNullException("msg"); } CorrelationService.InvalidateCorrelationToken(this, interfaceType, operation, message.Args); IdentityContextData identityData = (IdentityContextData)message.LogicalCallContext.GetData(IdentityContextData.IdentityContext); InboundActivityHelper.ValidateRoles(this, identityData.Identity); ProcessParameters(context, message, interfaceType, operation); RaiseEvent(WebServiceInputActivity.InputReceivedEvent, this, EventArgs.Empty); } private void ProcessParameters(ActivityExecutionContext context, IMethodMessage message, Type interfaceType, string operation) { WorkflowParameterBindingCollection parameters = ParameterBindings; if (parameters == null) return; //cache mInfo todo MethodInfo mInfo = interfaceType.GetMethod(operation); if (mInfo == null) return; int index = 0; bool responseRequired = false; foreach (ParameterInfo formalParameter in mInfo.GetParameters()) { // populate in params, checking on IsIn alone is not sufficient if (!(formalParameter.ParameterType.IsByRef || (formalParameter.IsIn && formalParameter.IsOut))) { if (parameters.Contains(formalParameter.Name)) { WorkflowParameterBinding binding = parameters[formalParameter.Name]; binding.Value = message.Args[index++]; } } else { responseRequired = true; } } if (mInfo.ReturnType != typeof(void) || responseRequired) { // create queue entry {interface, operation and receive activity Id} IComparable queueId = new EventQueueName(interfaceType, operation, QualifiedName); // enqueue the message for sendresponse reply context WorkflowQueuingService queuingService = (WorkflowQueuingService)context.GetService(typeof(WorkflowQueuingService)); if (!queuingService.Exists(queueId)) queuingService.CreateWorkflowQueue(queueId, true); queuingService.GetWorkflowQueue(queueId).Enqueue(message); } } protected sealed override ActivityExecutionStatus HandleFault(ActivityExecutionContext executionContext, Exception exception) { if (executionContext == null) throw new ArgumentNullException("executionContext"); if (exception == null) throw new ArgumentNullException("exception"); ActivityExecutionStatus newStatus = this.Cancel(executionContext); if (newStatus == ActivityExecutionStatus.Canceling) return ActivityExecutionStatus.Faulting; return newStatus; } protected sealed override ActivityExecutionStatus Cancel(ActivityExecutionContext executionContext) { if (executionContext == null) throw new ArgumentNullException("executionContext"); UnsubscribeForActivity(executionContext); return ActivityExecutionStatus.Closed; } private void UnsubscribeForActivity(ActivityExecutionContext context) { if (this.ActivitySubscribed) { CorrelationService.Unsubscribe(context, this, this.InterfaceType, this.MethodName, this); this.ActivitySubscribed = false; } } void IActivityEventListener.OnEvent(object sender, QueueEventArgs e) { ActivityExecutionContext context = (ActivityExecutionContext)sender; WebServiceInputActivity activity = context.Activity as WebServiceInputActivity; // if activity is not scheduled for execution do not dequeue the message if (activity.ExecutionStatus != ActivityExecutionStatus.Executing) return; ActivityExecutionStatus status = ExecuteForActivity(context, activity.InterfaceType, activity.MethodName); if (status == ActivityExecutionStatus.Closed) { UnsubscribeForActivity(context); context.CloseActivity(); } } #endregion #region IEventActivity members void IEventActivity.Subscribe(ActivityExecutionContext parentContext, IActivityEventListener parentEventHandler) { if (parentContext == null) throw new ArgumentNullException("parentContext"); if (parentEventHandler == null) throw new ArgumentNullException("parentEventHandler"); CorrelationService.Subscribe(parentContext, this, this.InterfaceType, this.MethodName, parentEventHandler, this.WorkflowInstanceId); } void IEventActivity.Unsubscribe(ActivityExecutionContext parentContext, IActivityEventListener parentEventHandler) { if (parentContext == null) throw new ArgumentNullException("parentContext"); if (parentEventHandler == null) throw new ArgumentNullException("parentEventHandler"); CorrelationService.Unsubscribe(parentContext, this, this.InterfaceType, this.MethodName, parentEventHandler); } IComparable IEventActivity.QueueName { get { return (IComparable)this.GetValue(QueueNameProperty); } } #endregion #region IDynamicPropertyTypeProvider Type IDynamicPropertyTypeProvider.GetPropertyType(IServiceProvider serviceProvider, string propertyName) { if (propertyName == null) throw new ArgumentNullException("propertyName"); Dictionary parameters = new Dictionary(); this.GetParameterPropertyDescriptors(parameters); if (parameters.ContainsKey(propertyName)) { ParameterInfoBasedPropertyDescriptor descriptor = parameters[propertyName] as ParameterInfoBasedPropertyDescriptor; if (descriptor != null) return descriptor.ParameterType; } return null; } AccessTypes IDynamicPropertyTypeProvider.GetAccessType(IServiceProvider serviceProvider, string propertyName) { if (propertyName == null) throw new ArgumentNullException("propertyName"); return AccessTypes.Read; } internal void GetParameterPropertyDescriptors(IDictionary properties) { if (((IComponent)this).Site == null) return; ITypeProvider typeProvider = (ITypeProvider)((IComponent)this).Site.GetService(typeof(ITypeProvider)); if (typeProvider == null) throw new InvalidOperationException(SR.GetString(SR.General_MissingService, typeof(ITypeProvider).FullName)); Type type = null; if (this.InterfaceType != null) type = typeProvider.GetType(this.InterfaceType.AssemblyQualifiedName); if (type != null && type.IsInterface) { MethodInfo method = Helpers.GetInterfaceMethod(type, this.MethodName); if (method != null && WebServiceActivityHelpers.ValidateParameterTypes(method).Count == 0) { List inputParameters, outParameters; WebServiceActivityHelpers.GetParameterInfo(method, out inputParameters, out outParameters); foreach (ParameterInfo paramInfo in inputParameters) { PropertyDescriptor prop = new ParameterInfoBasedPropertyDescriptor(typeof(WebServiceInputActivity), paramInfo, true, DesignOnlyAttribute.Yes); properties[prop.Name] = prop; } } } } #endregion } internal sealed class WebServiceReceiveValidator : ActivityValidator { public override ValidationErrorCollection Validate(ValidationManager manager, object obj) { ValidationErrorCollection validationErrors = base.Validate(manager, obj); WebServiceInputActivity webServiceReceive = obj as WebServiceInputActivity; if (webServiceReceive == null) throw new ArgumentException(SR.GetString(SR.Error_UnexpectedArgumentType, typeof(WebServiceInputActivity).FullName), "obj"); if (Helpers.IsActivityLocked(webServiceReceive)) { return validationErrors; } if (webServiceReceive.IsActivating) { if (WebServiceActivityHelpers.GetPreceedingActivities(webServiceReceive).GetEnumerator().MoveNext() == true) { ValidationError error = new ValidationError(SR.GetString(SR.Error_ActivationActivityNotFirst), ErrorNumbers.Error_ActivationActivityNotFirst); error.PropertyName = "IsActivating"; validationErrors.Add(error); return validationErrors; } if (WebServiceActivityHelpers.IsInsideLoop(webServiceReceive, null)) { ValidationError error = new ValidationError(SR.GetString(SR.Error_ActivationActivityInsideLoop), ErrorNumbers.Error_ActivationActivityInsideLoop); error.PropertyName = "IsActivating"; validationErrors.Add(error); return validationErrors; } } else { if (WebServiceActivityHelpers.GetPreceedingActivities(webServiceReceive, true).GetEnumerator().MoveNext() == false) { ValidationError error = new ValidationError(SR.GetString(SR.Error_WebServiceReceiveNotMarkedActivate), ErrorNumbers.Error_WebServiceReceiveNotMarkedActivate); error.PropertyName = "IsActivating"; validationErrors.Add(error); return validationErrors; } } ITypeProvider typeProvider = (ITypeProvider)manager.GetService(typeof(ITypeProvider)); if (typeProvider == null) throw new InvalidOperationException(SR.GetString(SR.General_MissingService, typeof(ITypeProvider).FullName)); Type interfaceType = null; if (webServiceReceive.InterfaceType != null) interfaceType = typeProvider.GetType(webServiceReceive.InterfaceType.AssemblyQualifiedName); if (interfaceType == null) { ValidationError error = new ValidationError(SR.GetString(SR.Error_TypePropertyInvalid, "InterfaceType"), ErrorNumbers.Error_PropertyNotSet); error.PropertyName = "InterfaceType"; validationErrors.Add(error); } else if (!interfaceType.IsInterface) { ValidationError error = new ValidationError(SR.GetString(SR.Error_InterfaceTypeNotInterface, "InterfaceType"), ErrorNumbers.Error_InterfaceTypeNotInterface); error.PropertyName = "InterfaceType"; validationErrors.Add(error); } else { // Validate method if (String.IsNullOrEmpty(webServiceReceive.MethodName)) validationErrors.Add(ValidationError.GetNotSetValidationError("MethodName")); else { MethodInfo methodInfo = Helpers.GetInterfaceMethod(interfaceType, webServiceReceive.MethodName); if (methodInfo == null) { ValidationError error = new ValidationError(SR.GetString(SR.Error_MethodNotExists, "MethodName", webServiceReceive.MethodName), ErrorNumbers.Error_MethodNotExists); error.PropertyName = "MethodName"; validationErrors.Add(error); } else { ValidationErrorCollection parameterTypeErrors = WebServiceActivityHelpers.ValidateParameterTypes(methodInfo); if (parameterTypeErrors.Count > 0) { foreach (ValidationError parameterTypeError in parameterTypeErrors) { parameterTypeError.PropertyName = "MethodName"; } validationErrors.AddRange(parameterTypeErrors); } else { List inputParameters, outParameters; WebServiceActivityHelpers.GetParameterInfo(methodInfo, out inputParameters, out outParameters); // Check to see if all input parameters have a valid binding. foreach (ParameterInfo paramInfo in inputParameters) { string paramName = paramInfo.Name; string parameterPropertyName = ParameterInfoBasedPropertyDescriptor.GetParameterPropertyName(webServiceReceive.GetType(), paramName); Type paramType = paramInfo.ParameterType.IsByRef ? paramInfo.ParameterType.GetElementType() : paramInfo.ParameterType; object paramValue = null; if (webServiceReceive.ParameterBindings.Contains(paramName)) { if (webServiceReceive.ParameterBindings[paramName].IsBindingSet(WorkflowParameterBinding.ValueProperty)) paramValue = webServiceReceive.ParameterBindings[paramName].GetBinding(WorkflowParameterBinding.ValueProperty); else paramValue = webServiceReceive.ParameterBindings[paramName].GetValue(WorkflowParameterBinding.ValueProperty); } if (!paramType.IsPublic || !paramType.IsSerializable) { ValidationError validationError = new ValidationError(SR.GetString(SR.Error_TypeNotPublicSerializable, paramName, paramType.FullName), ErrorNumbers.Error_TypeNotPublicSerializable); validationError.PropertyName = parameterPropertyName; validationErrors.Add(validationError); } else if (!webServiceReceive.ParameterBindings.Contains(paramName) || paramValue == null) { ValidationError validationError = ValidationError.GetNotSetValidationError(paramName); validationError.PropertyName = parameterPropertyName; validationErrors.Add(validationError); } else { AccessTypes access = AccessTypes.Read; if (paramInfo.ParameterType.IsByRef) access |= AccessTypes.Write; ValidationErrorCollection variableErrors = ValidationHelpers.ValidateProperty(manager, webServiceReceive, paramValue, new PropertyValidationContext(webServiceReceive.ParameterBindings[paramName], null, paramName), new BindValidationContext(paramInfo.ParameterType.IsByRef ? paramInfo.ParameterType.GetElementType() : paramInfo.ParameterType, access)); foreach (ValidationError validationError in variableErrors) validationError.PropertyName = parameterPropertyName; validationErrors.AddRange(variableErrors); } } if (webServiceReceive.ParameterBindings.Count > inputParameters.Count) validationErrors.Add(new ValidationError(SR.GetString(SR.Warning_AdditionalBindingsFound), ErrorNumbers.Warning_AdditionalBindingsFound, true)); bool foundMatchingResponse = false; foreach (Activity succeedingActivity in WebServiceActivityHelpers.GetSucceedingActivities(webServiceReceive)) { if ((succeedingActivity is WebServiceOutputActivity && ((WebServiceOutputActivity)succeedingActivity).InputActivityName == webServiceReceive.Name) || (succeedingActivity is WebServiceFaultActivity && ((WebServiceFaultActivity)succeedingActivity).InputActivityName == webServiceReceive.Name)) { foundMatchingResponse = true; break; } } // If the method has out parameters or is the method has a return value, // check to see if there are any corresponding WebServiceResponse activities. if ((outParameters.Count > 0 || methodInfo.ReturnType != typeof(void)) && !foundMatchingResponse) { validationErrors.Add(new ValidationError(SR.GetString(SR.Error_WebServiceResponseNotFound), ErrorNumbers.Error_WebServiceResponseNotFound)); } } } } } return validationErrors; } } internal sealed class WebServiceCodeGenerator : ActivityCodeGenerator { public override void GenerateCode(CodeGenerationManager manager, object obj) { WebServiceInputActivity webserviceInput = obj as WebServiceInputActivity; if (manager == null) throw new ArgumentNullException("manager"); if (obj == null) throw new ArgumentNullException("obj"); if (webserviceInput == null) return; ITypeProvider typeProvider = manager.GetService(typeof(ITypeProvider)) as ITypeProvider; if (typeProvider == null) throw new InvalidOperationException(SR.GetString(SR.General_MissingService, typeof(ITypeProvider).FullName)); CodeNamespaceCollection codeNamespaces = manager.Context[typeof(CodeNamespaceCollection)] as CodeNamespaceCollection; if (codeNamespaces == null) throw new InvalidOperationException(SR.GetString(SR.Error_ContextStackItemMissing, typeof(CodeNamespaceCollection).Name)); CodeTypeDeclaration webServiceClass = CreateOrGetServiceDeclaration(Helpers.GetRootActivity(webserviceInput), codeNamespaces); Debug.Assert(webserviceInput.InterfaceType != null, "Interface type should not be null"); if (webserviceInput.InterfaceType != null) { bool memberExists = false; MethodInfo methodInfo = Helpers.GetInterfaceMethod(webserviceInput.InterfaceType, webserviceInput.MethodName); //Check to see if a method with the same name already exists (the same activity may be used // in multiple places). SupportedLanguages language = CompilerHelpers.GetSupportedLanguage(manager); foreach (CodeTypeMember member in webServiceClass.Members) { // if (member is CodeMemberMethod && String.Compare(member.Name, methodInfo.Name, language == SupportedLanguages.CSharp ? StringComparison.InvariantCulture : StringComparison.InvariantCultureIgnoreCase) == 0) memberExists = true; } if (!memberExists) webServiceClass.Members.Add(this.GetWebServiceMethodDeclaraion(methodInfo, webserviceInput.IsActivating, language)); } base.GenerateCode(manager, obj); return; } [SuppressMessage("Microsoft.Globalization", "CA1307:SpecifyStringComparison", Justification = "IndexOf(\".\") not a security issue.")] private CodeTypeDeclaration CreateOrGetServiceDeclaration(Activity rootActivity, CodeNamespaceCollection codeNamespaceCollection) { String namespaceName = ""; CodeNamespace webServiceCodeNamespace = null; string className = rootActivity.GetType().FullName; CodeTypeDeclaration webServiceClass = null; if (rootActivity.GetType().FullName.IndexOf(".") != -1) namespaceName = rootActivity.GetType().FullName.Substring(0, rootActivity.GetType().FullName.LastIndexOf('.')); foreach (CodeNamespace codeNamespace in codeNamespaceCollection) { if (codeNamespace.Name == namespaceName) { webServiceCodeNamespace = codeNamespace; break; } } if (webServiceCodeNamespace == null) { webServiceCodeNamespace = this.GetWebServiceCodeNamespace(namespaceName); codeNamespaceCollection.Add(webServiceCodeNamespace); } String webServiceTypeName = className.Substring(className.LastIndexOf('.') + 1) + "_WebService"; foreach (CodeTypeDeclaration codeTypeDeclaration in webServiceCodeNamespace.Types) { if (codeTypeDeclaration.Name == webServiceTypeName) { webServiceClass = codeTypeDeclaration; break; } } if (webServiceClass == null) { webServiceClass = this.GetWebserviceCodeTypeDeclaration(className.Substring(className.LastIndexOf('.') + 1)); webServiceCodeNamespace.Types.Add(webServiceClass); //Ensure namespaces are imported. webServiceCodeNamespace.Imports.Add(new CodeNamespaceImport("System")); webServiceCodeNamespace.Imports.Add(new CodeNamespaceImport("System.Web")); webServiceCodeNamespace.Imports.Add(new CodeNamespaceImport("System.Web.Services")); webServiceCodeNamespace.Imports.Add(new CodeNamespaceImport("System.Web.Services.Protocols")); webServiceCodeNamespace.Imports.Add(new CodeNamespaceImport("System.Workflow.Runtime.Hosting")); webServiceCodeNamespace.Imports.Add(new CodeNamespaceImport("System.Workflow.Activities")); } return webServiceClass; } private CodeNamespace GetWebServiceCodeNamespace(string namespaceName) { CodeNamespace nameSpace = new CodeNamespace(namespaceName); return nameSpace; } //[WebServiceBinding(ConformsTo=WsiClaims.BP10,EmitConformanceClaims = true)] //public class _WebService : System.Workflow.Runtime.Hosting.WorkflowWebService //{ // public _WebService():base(typeof()) {} //} private CodeTypeDeclaration GetWebserviceCodeTypeDeclaration(string workflowTypeName) { CodeTypeDeclaration typeDeclaration = new CodeTypeDeclaration(workflowTypeName + "_WebService"); typeDeclaration.BaseTypes.Add(new CodeTypeReference("WorkflowWebService")); CodeAttributeDeclaration attributeDeclaration = new CodeAttributeDeclaration("WebServiceBinding", new CodeAttributeArgument("ConformsTo", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression("WsiProfiles"), "BasicProfile1_1")), new CodeAttributeArgument("EmitConformanceClaims", new CodePrimitiveExpression(true))); typeDeclaration.CustomAttributes.Add(attributeDeclaration); //Emit Constructor CodeConstructor constructor = new CodeConstructor(); constructor.Attributes = MemberAttributes.Public; constructor.BaseConstructorArgs.Add(new CodeTypeOfExpression(workflowTypeName)); typeDeclaration.Members.Add(constructor); return typeDeclaration; } //[WebMethod(Description=, EnableSession=true)] //public virtual () //{ // For No out ref case. // return ()base.Invoke(, , true | false(based on activation), arguments)[0]; // // For out & ref case. // Object[] results = base.Invoke(, , true | false(based on activation), arguments); // refParam1 = (RPType)results[1]; // refParam2 = (RPType)results[2]; // outParam3 = (RPType)results[3]; // return ()results[0]; //} private CodeMemberMethod GetWebServiceMethodDeclaraion(MethodInfo methodInfo, bool isActivation, SupportedLanguages language) { CodeMemberMethod webMethod = new CodeMemberMethod(); webMethod.Attributes = MemberAttributes.Public; webMethod.ReturnType = new CodeTypeReference(methodInfo.ReturnType); webMethod.Name = methodInfo.Name; CodeAttributeDeclaration attrDecl = new CodeAttributeDeclaration("WebMethodAttribute"); attrDecl.Arguments.Add(new CodeAttributeArgument("Description", new CodePrimitiveExpression(methodInfo.Name))); attrDecl.Arguments.Add(new CodeAttributeArgument("EnableSession", new CodePrimitiveExpression(false))); webMethod.CustomAttributes.Add(attrDecl); List outRefParams = new List(); CodeArrayCreateExpression paramArrayCreationExpression = new CodeArrayCreateExpression(); paramArrayCreationExpression.CreateType = new CodeTypeReference(typeof(Object)); foreach (ParameterInfo paramInfo in methodInfo.GetParameters()) { CodeParameterDeclarationExpression paramDecl = new CodeParameterDeclarationExpression(); if (paramInfo.IsOut || paramInfo.ParameterType.IsByRef) { paramDecl.Type = new CodeTypeReference(paramInfo.ParameterType.GetElementType().FullName); paramDecl.Direction = paramInfo.IsOut ? FieldDirection.Out : FieldDirection.Ref; if (paramDecl.Direction == FieldDirection.Out && language == SupportedLanguages.VB) paramDecl.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeTypeReference(typeof(System.Runtime.InteropServices.OutAttribute)))); outRefParams.Add(paramInfo); } else { paramDecl.Type = new CodeTypeReference(paramInfo.ParameterType.FullName); } paramDecl.Name = paramInfo.Name; webMethod.Parameters.Add(paramDecl); if (!paramInfo.IsOut) paramArrayCreationExpression.Initializers.Add(new CodeArgumentReferenceExpression(paramInfo.Name)); } //Emit method body CodeMethodInvokeExpression baseInvokeExpression = new CodeMethodInvokeExpression(); baseInvokeExpression.Method = new CodeMethodReferenceExpression(new CodeThisReferenceExpression(), "Invoke"); baseInvokeExpression.Parameters.Add(new CodeTypeOfExpression(methodInfo.DeclaringType)); baseInvokeExpression.Parameters.Add(new CodePrimitiveExpression(methodInfo.Name)); baseInvokeExpression.Parameters.Add(new CodePrimitiveExpression(isActivation)); baseInvokeExpression.Parameters.Add(paramArrayCreationExpression); int iStartIndex = (methodInfo.ReturnType == typeof(void)) ? 0 : 1; if (outRefParams.Count != 0) { //Results variable declaration CodeVariableDeclarationStatement resultsDeclaration = new CodeVariableDeclarationStatement(new CodeTypeReference(new CodeTypeReference(typeof(Object)), 1), "results"); resultsDeclaration.InitExpression = baseInvokeExpression; webMethod.Statements.Add(resultsDeclaration); for (int i = 0; i < outRefParams.Count; ++i) { ParameterInfo pinfo = outRefParams[i]; CodeAssignStatement assignStatement = new CodeAssignStatement(); CodeExpression leftExpression = new CodeArgumentReferenceExpression(pinfo.Name); CodeExpression rightExpression = new CodeCastExpression(new CodeTypeReference(pinfo.ParameterType.GetElementType().FullName), new CodeIndexerExpression(new CodeVariableReferenceExpression("results"), new CodePrimitiveExpression(i + iStartIndex))); assignStatement.Left = leftExpression; assignStatement.Right = rightExpression; webMethod.Statements.Add(assignStatement); } } if (methodInfo.ReturnType != typeof(void)) { CodeExpression returnTargetExpression; if (outRefParams.Count != 0) returnTargetExpression = new CodeVariableReferenceExpression("results"); else returnTargetExpression = baseInvokeExpression; CodeMethodReturnStatement methodReturnStatement = new CodeMethodReturnStatement(new CodeCastExpression(methodInfo.ReturnType, new CodeIndexerExpression(returnTargetExpression, new CodePrimitiveExpression(0)))); webMethod.Statements.Add(methodReturnStatement); } else if (outRefParams.Count == 0 && methodInfo.ReturnType == typeof(void)) { webMethod.Statements.Add(baseInvokeExpression); } return webMethod; } } internal sealed class InterfaceTypeFilterProvider : ITypeFilterProvider { private IServiceProvider serviceProvider; public InterfaceTypeFilterProvider(IServiceProvider serviceProvider) { this.serviceProvider = serviceProvider; } public bool CanFilterType(Type type, bool throwOnError) { if (throwOnError && !type.IsInterface) throw new Exception(SR.GetString(SR.Error_InterfaceTypeNotInterface, "InterfaceType")); return type.IsInterface; } public string FilterDescription { get { return SR.GetString(SR.InterfaceTypeFilterDescription); } } } }