using System;
using System.CodeDom;
+using System.CodeDom.Compiler;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Serialization;
ImportInfo iinfo;
XmlSchemas xmlSchemas;
XmlSchemas soapSchemas;
+
+#if NET_2_0
+ ArrayList asyncTypes = new ArrayList ();
+#endif
#endregion // Fields
{
get { return soapSchemas; }
}
+
+#if NET_2_0
+ internal CodeGenerationOptions CodeGenerationOptions {
+ get { return descriptionImporter.CodeGenerationOptions; }
+ }
+
+ internal ICodeGenerator CodeGenerator {
+ get { return descriptionImporter.CodeGenerator; }
+ }
+
+ internal ImportContext ImportContext {
+ get { return descriptionImporter.Context; }
+ }
+#endif
#endregion // Properties
}
}
}
+
+ if (!found)
+ {
+ // Looks like MS.NET generates classes for all bindings if
+ // no services are present
+
+ foreach (ImportInfo info in importInfo)
+ {
+ this.iinfo = info;
+ foreach (Binding b in info.ServiceDescription.Bindings)
+ {
+ this.binding = b;
+ this.service = null;
+ this.port = null;
+ if (!IsBindingSupported ()) continue;
+ found = true;
+ ImportPortBinding (true);
+ }
+ }
+ }
EndNamespace ();
void ImportPortBinding (bool multipleBindings)
{
- if (multipleBindings) className = port.Name;
- else className = service.Name;
+ if (port != null) {
+ if (multipleBindings) className = port.Name;
+ else className = service.Name;
+ }
+ else
+ className = binding.Name;
className = classNames.AddUnique (CodeIdentifier.MakeValid (className), port);
className = className.Replace ("_x0020_", ""); // MS.NET seems to do this
CodeTypeDeclaration codeClass = BeginClass ();
codeTypeDeclaration = codeClass;
- AddCodeType (codeClass, port.Documentation);
+ AddCodeType (codeClass, port != null ? port.Documentation : null);
codeClass.Attributes = MemberAttributes.Public;
-
- if (service.Documentation != null && service.Documentation != "")
+
+ if (service != null && 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;
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)
else return msg.Name;
}
- internal string GetServiceUrl (string location)
+ internal void GenerateServiceUrl (string location, CodeStatementCollection stms)
{
- if (ImportInfo.AppSettingUrlKey == null || ImportInfo.AppSettingUrlKey == string.Empty)
- return location;
+ if (ImportInfo.AppSettingUrlKey == null || ImportInfo.AppSettingUrlKey == string.Empty) {
+ if (location != null) {
+ CodeExpression ce = new CodeFieldReferenceExpression (new CodeThisReferenceExpression(), "Url");
+ CodeAssignStatement cas = new CodeAssignStatement (ce, new CodePrimitiveExpression (location));
+ stms.Add (cas);
+ }
+ }
else
{
- string url;
- if (Style == ServiceDescriptionImportStyle.Server) throw new InvalidOperationException ("Cannot set appSettingUrlKey if Style is Server");
- url = ConfigurationSettings.AppSettings [ImportInfo.AppSettingUrlKey];
- if (ImportInfo.AppSettingBaseUrl != null && ImportInfo.AppSettingBaseUrl != string.Empty)
- url += "/" + ImportInfo.AppSettingBaseUrl + "/" + location;
- return url;
+ CodeExpression prop = new CodePropertyReferenceExpression (new CodeTypeReferenceExpression ("System.Configuration.ConfigurationSettings"), "AppSettings");
+ prop = new CodeIndexerExpression (prop, new CodePrimitiveExpression (ImportInfo.AppSettingUrlKey));
+ stms.Add (new CodeVariableDeclarationStatement (typeof(string), "urlSetting", prop));
+
+ CodeExpression urlSetting = new CodeVariableReferenceExpression ("urlSetting");
+ CodeExpression thisUrl = new CodeFieldReferenceExpression (new CodeThisReferenceExpression(), "Url");
+
+ CodeStatement[] trueStms = new CodeStatement [1];
+ CodeExpression ce = urlSetting;
+ CodeExpression cond = new CodeBinaryOperatorExpression (urlSetting, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression (null));
+
+ if (ImportInfo.AppSettingBaseUrl != null)
+ ce = new CodeMethodInvokeExpression (new CodeTypeReferenceExpression (typeof(string)), "Concat", ce, new CodePrimitiveExpression (ImportInfo.AppSettingBaseUrl));
+ trueStms [0] = new CodeAssignStatement (thisUrl, ce);
+
+ if (location != null) {
+ CodeStatement[] falseStms = new CodeStatement [1];
+ falseStms [0] = new CodeAssignStatement (thisUrl, new CodePrimitiveExpression (location));
+ stms.Add (new CodeConditionStatement (cond, trueStms, falseStms));
+ }
+ else
+ stms.Add (new CodeConditionStatement (cond, trueStms));
}
}
-
+
void ClasifySchemas (ArrayList importInfo)
{
// I don't like this, but I could not find any other way of clasifying
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)
{