Browse Source

* HttpSimpleProtocolImporter.cs: Implemented internal method to support
the new asyc model.
* ProtocolImporter.cs: Generate code for the new async model.
Added support for generating server skeletons in addition to client
proxies.
* ServiceDescriptionImporter.cs: Removed unneded check.
* SoapProtocolImporter.cs: Added support for generating server skeletons in
addition to client proxies.

svn path=/trunk/mcs/; revision=31479

Lluis Sanchez 21 years ago
parent
commit
7e9f3e17a2

+ 11 - 0
mcs/class/System.Web.Services/System.Web.Services.Description/ChangeLog

@@ -1,3 +1,14 @@
+2004-07-26  Lluis Sanchez Gual  <[email protected]>
+
+	* HttpSimpleProtocolImporter.cs: Implemented internal method to support
+	  the new asyc model.
+	* ProtocolImporter.cs: Generate code for the new async model.
+	  Added support for generating server skeletons in addition to client
+	  proxies.
+	* ServiceDescriptionImporter.cs: Removed unneded check.
+	* SoapProtocolImporter.cs: Added support for generating server skeletons in
+	  addition to client proxies.
+
 2004-07-23  Lluis Sanchez Gual  <[email protected]>
 
 	* ServiceDescriptionImporter.cs: Fixed bug when getting documents from a

+ 21 - 0
mcs/class/System.Web.Services/System.Web.Services.Description/HttpSimpleProtocolImporter.cs

@@ -280,6 +280,27 @@ namespace System.Web.Services.Description
 			
 			return method;
 		}		
+
+#if NET_2_0
+		internal override CodeExpression BuildInvokeAsync (string messageName, CodeArrayCreateExpression paramsArray, CodeExpression delegateField, CodeExpression userStateVar)
+		{
+			HttpOperationBinding httpOper = OperationBinding.Extensions.Find (typeof (HttpOperationBinding)) as HttpOperationBinding;
+			
+			CodeThisReferenceExpression ethis = new CodeThisReferenceExpression();
+			
+			CodeExpression thisURlExp = new CodeFieldReferenceExpression (ethis, "Url");
+			CodePrimitiveExpression metUrl = new CodePrimitiveExpression (httpOper.Location);
+			CodeBinaryOperatorExpression expMethodLocation = new CodeBinaryOperatorExpression (thisURlExp, CodeBinaryOperatorType.Add, metUrl);
+			
+			CodeMethodInvokeExpression inv2 = new CodeMethodInvokeExpression (ethis, "InvokeAsync");
+			inv2.Parameters.Add (new CodePrimitiveExpression (messageName));
+			inv2.Parameters.Add (expMethodLocation);
+			inv2.Parameters.Add (paramsArray);
+			inv2.Parameters.Add (delegateField);
+			inv2.Parameters.Add (userStateVar);
+			return inv2;
+		}
+#endif
 		
 		protected virtual Type GetInMimeFormatter ()
 		{

+ 213 - 6
mcs/class/System.Web.Services/System.Web.Services.Description/ProtocolImporter.cs

@@ -65,6 +65,10 @@ namespace System.Web.Services.Description {
 		ImportInfo iinfo;
 		XmlSchemas xmlSchemas;
 		XmlSchemas soapSchemas;
+		
+#if NET_2_0
+		ArrayList asyncTypes = new ArrayList ();
+#endif
 
 		#endregion // Fields
 
@@ -261,12 +265,16 @@ namespace System.Web.Services.Description {
 				if (service.Documentation != null && service.Documentation != "")
 					AddComments (codeClass, service.Documentation);
 
-				CodeAttributeDeclaration att = new CodeAttributeDeclaration ("System.Diagnostics.DebuggerStepThroughAttribute");
-				AddCustomAttribute (codeClass, att, true);
-
-				att = new CodeAttributeDeclaration ("System.ComponentModel.DesignerCategoryAttribute");
-				att.Arguments.Add (GetArg ("code"));
-				AddCustomAttribute (codeClass, att, true);
+				if (Style == ServiceDescriptionImportStyle.Client) {
+					CodeAttributeDeclaration att = new CodeAttributeDeclaration ("System.Diagnostics.DebuggerStepThroughAttribute");
+					AddCustomAttribute (codeClass, att, true);
+	
+					att = new CodeAttributeDeclaration ("System.ComponentModel.DesignerCategoryAttribute");
+					att.Arguments.Add (GetArg ("code"));
+					AddCustomAttribute (codeClass, att, true);
+				}
+				else
+					codeClass.TypeAttributes = System.Reflection.TypeAttributes.Abstract | System.Reflection.TypeAttributes.Public;
 
 				if (binding.Operations.Count == 0) {
 					warnings |= ServiceDescriptionImportWarnings.NoMethodsGenerated;
@@ -297,9 +305,18 @@ namespace System.Web.Services.Description {
 						methodName = method.Name;
 						if (operation.Documentation != null && operation.Documentation != "")
 							AddComments (method, operation.Documentation);
+#if NET_2_0
+						if (Style == ServiceDescriptionImportStyle.Client)
+							AddAsyncMembers (method.Name, method);
+#endif
 					}
 				}
 				
+#if NET_2_0
+			if (Style == ServiceDescriptionImportStyle.Client)
+				AddAsyncTypes ();
+#endif
+				
 				EndClass ();
 			}
 			catch (InvalidOperationException ex)
@@ -484,6 +501,196 @@ namespace System.Web.Services.Description {
 			return false;
 		}
 		
+#if NET_2_0
+
+		void AddAsyncTypes ()
+		{
+			foreach (CodeTypeDeclaration type in asyncTypes)
+				codeNamespace.Types.Add (type);
+			asyncTypes.Clear ();
+		}
+
+		void AddAsyncMembers (string messageName, CodeMemberMethod method)
+		{
+			CodeThisReferenceExpression ethis = new CodeThisReferenceExpression();
+			CodePrimitiveExpression enull = new CodePrimitiveExpression (null);
+			
+			CodeMemberField codeField = new CodeMemberField (typeof(System.Threading.SendOrPostCallback), messageName + "OperationCompleted");
+			codeField.Attributes = MemberAttributes.Private;
+			CodeTypeDeclaration.Members.Add (codeField);
+			
+			// Event arguments class
+			
+			string argsClassName = classNames.AddUnique (messageName + "CompletedEventArgs", null);
+			CodeTypeDeclaration argsClass = new CodeTypeDeclaration (argsClassName);
+			argsClass.BaseTypes.Add (new CodeTypeReference ("System.ComponentModel.AsyncCompletedEventArgs"));
+
+			CodeMemberField resultsField = new CodeMemberField (typeof(object[]), "results");
+			resultsField.Attributes = MemberAttributes.Private;
+			argsClass.Members.Add (resultsField);
+			
+			CodeConstructor cc = new CodeConstructor ();
+			cc.Attributes = MemberAttributes.Assembly;
+			cc.Parameters.Add (new CodeParameterDeclarationExpression (typeof(object[]), "results"));
+			cc.Parameters.Add (new CodeParameterDeclarationExpression (typeof(System.Exception), "exception"));
+			cc.Parameters.Add (new CodeParameterDeclarationExpression (typeof(bool), "cancelled"));
+			cc.Parameters.Add (new CodeParameterDeclarationExpression (typeof(object), "userState"));
+			cc.BaseConstructorArgs.Add (new CodeVariableReferenceExpression ("exception"));
+			cc.BaseConstructorArgs.Add (new CodeVariableReferenceExpression ("cancelled"));
+			cc.BaseConstructorArgs.Add (new CodeVariableReferenceExpression ("userState"));
+			CodeExpression thisResults = new CodeFieldReferenceExpression (ethis, "results");
+			cc.Statements.Add (new CodeAssignStatement (thisResults, new CodeVariableReferenceExpression ("results")));
+			argsClass.Members.Add (cc);
+			
+			int ind = 0;
+			
+			if (method.ReturnType.BaseType != "System.Void")
+				argsClass.Members.Add (CreateArgsProperty (method.ReturnType, "Result", ind++));
+			
+			foreach (CodeParameterDeclarationExpression par in method.Parameters) 
+			{
+				if (par.Direction == FieldDirection.Out || par.Direction == FieldDirection.Ref)
+					argsClass.Members.Add (CreateArgsProperty (par.Type, par.Name, ind++));
+			}
+			
+			bool needsArgsClass = (ind > 0);
+			if (needsArgsClass)
+				asyncTypes.Add (argsClass);
+			else
+				argsClassName = "System.ComponentModel.AsyncCompletedEventArgs";
+			
+			// Event delegate type
+			
+			CodeTypeDelegate delegateType = new CodeTypeDelegate (messageName + "CompletedEventHandler");
+			delegateType.Parameters.Add (new CodeParameterDeclarationExpression (typeof(object), "sender"));
+			delegateType.Parameters.Add (new CodeParameterDeclarationExpression (argsClassName, "args"));
+			
+			// Event member
+			
+			CodeMemberEvent codeEvent = new CodeMemberEvent ();
+			codeEvent.Name = messageName + "Completed";
+			codeEvent.Type = new CodeTypeReference (delegateType.Name);
+			CodeTypeDeclaration.Members.Add (codeEvent);
+			
+			// Async method (without user state param)
+			
+			CodeMemberMethod am = new CodeMemberMethod ();
+			am.Attributes = MemberAttributes.Public | MemberAttributes.Final;
+			am.Name = method.Name + "Async";
+			am.ReturnType = new CodeTypeReference (typeof(void));
+			CodeMethodInvokeExpression inv;
+			inv = new CodeMethodInvokeExpression (ethis, am.Name);
+			am.Statements.Add (inv);
+			
+			// On...Completed method
+			
+			CodeMemberMethod onCompleted = new CodeMemberMethod ();
+			onCompleted.Name = "On" + messageName + "Completed";
+			onCompleted.Attributes = MemberAttributes.Private | MemberAttributes.Final;
+			onCompleted.ReturnType = new CodeTypeReference (typeof(void));
+			onCompleted.Parameters.Add (new CodeParameterDeclarationExpression (typeof(object), "arg"));
+			
+			CodeConditionStatement anIf = new CodeConditionStatement ();
+			
+			CodeExpression eventField = new CodeEventReferenceExpression (ethis, codeEvent.Name);
+			anIf.Condition = new CodeBinaryOperatorExpression (eventField, CodeBinaryOperatorType.IdentityInequality, enull);
+			CodeExpression castedArg = new CodeCastExpression (typeof(System.Web.Services.Protocols.InvokeCompletedEventArgs), new CodeVariableReferenceExpression ("arg"));
+			CodeStatement invokeArgs = new CodeVariableDeclarationStatement (typeof(System.Web.Services.Protocols.InvokeCompletedEventArgs), "invokeArgs", castedArg);
+			anIf.TrueStatements.Add (invokeArgs);
+			
+			CodeDelegateInvokeExpression delegateInvoke = new CodeDelegateInvokeExpression ();
+			delegateInvoke.TargetObject = eventField;
+			delegateInvoke.Parameters.Add (ethis);
+			CodeObjectCreateExpression argsInstance = new CodeObjectCreateExpression (argsClassName);
+			CodeExpression invokeArgsVar = new CodeVariableReferenceExpression ("invokeArgs");
+			if (needsArgsClass) argsInstance.Parameters.Add (new CodeFieldReferenceExpression (invokeArgsVar, "Results"));
+			argsInstance.Parameters.Add (new CodeFieldReferenceExpression (invokeArgsVar, "Error"));
+			argsInstance.Parameters.Add (new CodeFieldReferenceExpression (invokeArgsVar, "Cancelled"));
+			argsInstance.Parameters.Add (new CodeFieldReferenceExpression (invokeArgsVar, "UserState"));
+			delegateInvoke.Parameters.Add (argsInstance);
+			anIf.TrueStatements.Add (delegateInvoke);
+			
+			onCompleted.Statements.Add (anIf);
+			
+			// Async method
+			
+			CodeMemberMethod asyncMethod = new CodeMemberMethod ();
+			asyncMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final;
+			asyncMethod.Name = method.Name + "Async";
+			asyncMethod.ReturnType = new CodeTypeReference (typeof(void));
+			
+			CodeExpression delegateField = new CodeFieldReferenceExpression (ethis, codeField.Name);
+			anIf = new CodeConditionStatement ();
+			anIf.Condition = new CodeBinaryOperatorExpression (delegateField, CodeBinaryOperatorType.IdentityEquality, enull);;
+			CodeExpression delegateRef = new CodeMethodReferenceExpression (ethis, onCompleted.Name);
+			CodeExpression newDelegate = new CodeObjectCreateExpression (typeof(System.Threading.SendOrPostCallback), delegateRef);
+			CodeAssignStatement cas = new CodeAssignStatement (delegateField, newDelegate);
+			anIf.TrueStatements.Add (cas);
+			asyncMethod.Statements.Add (anIf);
+			
+			CodeArrayCreateExpression paramsArray = new CodeArrayCreateExpression (typeof(object));
+			
+			// Assign parameters
+			
+			CodeIdentifiers paramsIds = new CodeIdentifiers ();
+			
+			foreach (CodeParameterDeclarationExpression par in method.Parameters) 
+			{
+				paramsIds.Add (par.Name, null);
+				if (par.Direction == FieldDirection.In || par.Direction == FieldDirection.Ref) {
+					CodeParameterDeclarationExpression inpar = new CodeParameterDeclarationExpression (par.Type, par.Name);
+					am.Parameters.Add (inpar);
+					asyncMethod.Parameters.Add (inpar);
+					inv.Parameters.Add (new CodeVariableReferenceExpression (par.Name));
+					paramsArray.Initializers.Add (new CodeVariableReferenceExpression (par.Name));
+				}
+			}
+
+
+			inv.Parameters.Add (enull);
+			
+			string userStateName = paramsIds.AddUnique ("userState", null);
+			asyncMethod.Parameters.Add (new CodeParameterDeclarationExpression (typeof(object), userStateName));
+			
+			CodeExpression userStateVar = new CodeVariableReferenceExpression (userStateName);
+			asyncMethod.Statements.Add (BuildInvokeAsync (messageName, paramsArray, delegateField, userStateVar));
+			
+			CodeTypeDeclaration.Members.Add (am);
+			CodeTypeDeclaration.Members.Add (asyncMethod);
+			CodeTypeDeclaration.Members.Add (onCompleted);
+			
+			asyncTypes.Add (delegateType);
+		}
+		
+		CodeMemberProperty CreateArgsProperty (CodeTypeReference type, string name, int ind)
+		{
+			CodeMemberProperty prop = new CodeMemberProperty ();
+			prop.Attributes = MemberAttributes.Public | MemberAttributes.Final;
+			prop.HasGet = true;
+			prop.HasSet = false;
+			prop.Name = name;
+			prop.Type = type;
+			CodeThisReferenceExpression ethis = new CodeThisReferenceExpression();
+			CodeExpression thisResults = new CodeFieldReferenceExpression (ethis, "results");
+			prop.GetStatements.Add (new CodeMethodInvokeExpression (ethis, "RaiseExceptionIfNecessary"));
+			CodeArrayIndexerExpression arrValue = new CodeArrayIndexerExpression (thisResults, new CodePrimitiveExpression (ind));
+			CodeExpression retval = new CodeCastExpression (type, arrValue);
+			prop.GetStatements.Add (new CodeMethodReturnStatement (retval));
+			return prop;
+		}
+		
+		internal virtual CodeExpression BuildInvokeAsync (string messageName, CodeArrayCreateExpression paramsArray, CodeExpression delegateField, CodeExpression userStateVar)
+		{
+			CodeThisReferenceExpression ethis = new CodeThisReferenceExpression();
+			CodeMethodInvokeExpression inv2 = new CodeMethodInvokeExpression (ethis, "InvokeAsync");
+			inv2.Parameters.Add (new CodePrimitiveExpression (messageName));
+			inv2.Parameters.Add (paramsArray);
+			inv2.Parameters.Add (delegateField);
+			inv2.Parameters.Add (userStateVar);
+			return inv2;
+		}
+#endif
+		
 		[MonoTODO]
 		public void AddExtensionWarningComments (CodeCommentStatementCollection comments, ServiceDescriptionFormatExtensionCollection extensions) 
 		{

+ 1 - 3
mcs/class/System.Web.Services/System.Web.Services.Description/ServiceDescriptionImporter.cs

@@ -189,13 +189,11 @@ namespace System.Web.Services.Description {
 			
 			foreach (WebReference reference in webReferences) 
 			{
-				if (reference.AppSettingUrlKey != null && reference.AppSettingUrlKey == string.Empty && style == ServiceDescriptionImportStyle.Server)
-					throw new InvalidOperationException ("Cannot set appSettingUrlKey if Style is Server");
-				
 				ServiceDescriptionImporter importer = new ServiceDescriptionImporter ();
 				importer.CodeGenerator = codeGenerator;
 				importer.CodeGenerationOptions = options;
 				importer.Context = context;
+				importer.Style = style;
 				importer.ProtocolName = reference.ProtocolName;
 				
 				importer.AddReference (reference);

+ 64 - 44
mcs/class/System.Web.Services/System.Web.Services.Description/SoapProtocolImporter.cs

@@ -112,20 +112,31 @@ namespace System.Web.Services.Description {
 			if (sab != null) location = sab.Location;
 			string url = GetServiceUrl (location); 
 
-			CodeTypeReference ctr = new CodeTypeReference ("System.Web.Services.Protocols.SoapHttpClientProtocol");
-			codeClass.BaseTypes.Add (ctr);
+			if (Style == ServiceDescriptionImportStyle.Client) {
+				CodeTypeReference ctr = new CodeTypeReference ("System.Web.Services.Protocols.SoapHttpClientProtocol");
+				codeClass.BaseTypes.Add (ctr);
+			}
+			else {
+				CodeTypeReference ctr = new CodeTypeReference ("System.Web.Services.WebService");
+				codeClass.BaseTypes.Add (ctr);
+				CodeAttributeDeclaration attws = new CodeAttributeDeclaration ("System.Web.Services.WebServiceAttribute");
+				attws.Arguments.Add (GetArg ("Namespace", Port.Binding.Namespace));
+				AddCustomAttribute (codeClass, attws, true);
+			}
 			
 			CodeAttributeDeclaration att = new CodeAttributeDeclaration ("System.Web.Services.WebServiceBinding");
 			att.Arguments.Add (GetArg ("Name", Port.Name));
 			att.Arguments.Add (GetArg ("Namespace", Port.Binding.Namespace));
 			AddCustomAttribute (codeClass, att, true);
 	
-			CodeConstructor cc = new CodeConstructor ();
-			cc.Attributes = MemberAttributes.Public;
-			CodeExpression ce = new CodeFieldReferenceExpression (new CodeThisReferenceExpression(), "Url");
-			CodeAssignStatement cas = new CodeAssignStatement (ce, new CodePrimitiveExpression (url));
-			cc.Statements.Add (cas);
-			codeClass.Members.Add (cc);
+			if (Style == ServiceDescriptionImportStyle.Client) {
+				CodeConstructor cc = new CodeConstructor ();
+				cc.Attributes = MemberAttributes.Public;
+				CodeExpression ce = new CodeFieldReferenceExpression (new CodeThisReferenceExpression(), "Url");
+				CodeAssignStatement cas = new CodeAssignStatement (ce, new CodePrimitiveExpression (url));
+				cc.Statements.Add (cas);
+				codeClass.Members.Add (cc);
+			}
 			
 			memberIds = new CodeIdentifiers ();
 			headerVariables = new Hashtable ();
@@ -419,42 +430,48 @@ namespace System.Web.Services.Description {
 				}
 			}
 			
-			// Invoke call
-			
-			CodeThisReferenceExpression ethis = new CodeThisReferenceExpression();
-			CodePrimitiveExpression varMsgName = new CodePrimitiveExpression (messageName);
-			CodeMethodInvokeExpression inv;
-			CodeVariableDeclarationStatement dec;
-
-			inv = new CodeMethodInvokeExpression (ethis, "Invoke", varMsgName, methodParams);
-			if (outputMembers != null && outputMembers.Count > 0)
+			if (Style == ServiceDescriptionImportStyle.Client) 
 			{
-				dec = new CodeVariableDeclarationStatement (typeof(object[]), varResults, inv);
-				method.Statements.Add (dec);
-				method.Statements.AddRange (outAssign);
+				// Invoke call
+				
+				CodeThisReferenceExpression ethis = new CodeThisReferenceExpression();
+				CodePrimitiveExpression varMsgName = new CodePrimitiveExpression (messageName);
+				CodeMethodInvokeExpression inv;
+				CodeVariableDeclarationStatement dec;
+	
+				inv = new CodeMethodInvokeExpression (ethis, "Invoke", varMsgName, methodParams);
+				if (outputMembers != null && outputMembers.Count > 0)
+				{
+					dec = new CodeVariableDeclarationStatement (typeof(object[]), varResults, inv);
+					method.Statements.Add (dec);
+					method.Statements.AddRange (outAssign);
+				}
+				else
+					method.Statements.Add (inv);
+				
+				// Begin Invoke Call
+				
+				CodeExpression expCallb = new CodeVariableReferenceExpression (varCallback);
+				CodeExpression expAsyncs = new CodeVariableReferenceExpression (varAsyncState);
+				inv = new CodeMethodInvokeExpression (ethis, "BeginInvoke", varMsgName, methodParams, expCallb, expAsyncs);
+				methodBegin.Statements.Add (new CodeMethodReturnStatement (inv));
+				
+				// End Invoke call
+				
+				CodeExpression varAsyncr = new CodeVariableReferenceExpression (varAsyncResult);
+				inv = new CodeMethodInvokeExpression (ethis, "EndInvoke", varAsyncr);
+				if (outputMembers != null && outputMembers.Count > 0)
+				{
+					dec = new CodeVariableDeclarationStatement (typeof(object[]), varResults, inv);
+					methodEnd.Statements.Add (dec);
+					methodEnd.Statements.AddRange (outAssign);
+				}
+				else
+					methodEnd.Statements.Add (inv);
 			}
-			else
-				method.Statements.Add (inv);
-			
-			// Begin Invoke Call
-			
-			CodeExpression expCallb = new CodeVariableReferenceExpression (varCallback);
-			CodeExpression expAsyncs = new CodeVariableReferenceExpression (varAsyncState);
-			inv = new CodeMethodInvokeExpression (ethis, "BeginInvoke", varMsgName, methodParams, expCallb, expAsyncs);
-			methodBegin.Statements.Add (new CodeMethodReturnStatement (inv));
-			
-			// End Invoke call
-			
-			CodeExpression varAsyncr = new CodeVariableReferenceExpression (varAsyncResult);
-			inv = new CodeMethodInvokeExpression (ethis, "EndInvoke", varAsyncr);
-			if (outputMembers != null && outputMembers.Count > 0)
-			{
-				dec = new CodeVariableDeclarationStatement (typeof(object[]), varResults, inv);
-				methodEnd.Statements.Add (dec);
-				methodEnd.Statements.AddRange (outAssign);
+			else {
+				method.Attributes = MemberAttributes.Public | MemberAttributes.Abstract;
 			}
-			else
-				methodEnd.Statements.Add (inv);
 			
 			// Attributes
 			
@@ -462,7 +479,7 @@ namespace System.Web.Services.Description {
 			
 			CodeAttributeDeclaration att = new CodeAttributeDeclaration ("System.Web.Services.WebMethodAttribute");
 			if (messageName != method.Name) att.Arguments.Add (GetArg ("MessageName",messageName));
-			AddCustomAttribute (method, att, false);
+			AddCustomAttribute (method, att, (Style == ServiceDescriptionImportStyle.Server));
 			
 			if (style == SoapBindingStyle.Rpc)
 			{
@@ -500,8 +517,11 @@ namespace System.Web.Services.Description {
 			AddCustomAttribute (method, att, true);
 			
 			CodeTypeDeclaration.Members.Add (method);
-			CodeTypeDeclaration.Members.Add (methodBegin);
-			CodeTypeDeclaration.Members.Add (methodEnd);
+			
+			if (Style == ServiceDescriptionImportStyle.Client) {
+				CodeTypeDeclaration.Members.Add (methodBegin);
+				CodeTypeDeclaration.Members.Add (methodEnd);
+			}
 			
 			return method;
 		}