2 // System.Web.Services.Description.ProtocolImporter.cs
5 // Tim Coleman (tim@timcoleman.com)
6 // Lluis Sanchez Gual (lluis@ximian.com)
8 // Copyright (C) Tim Coleman, 2002
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System
.CodeDom
.Compiler
;
35 using System
.Web
.Services
;
36 using System
.Web
.Services
.Protocols
;
37 using System
.Xml
.Serialization
;
39 using System
.Xml
.Schema
;
40 using System
.Collections
;
41 using System
.Configuration
;
43 namespace System
.Web
.Services
.Description
{
44 public abstract class ProtocolImporter
{
50 CodeIdentifiers classNames
;
51 CodeNamespace codeNamespace
;
52 CodeCompileUnit codeCompileUnit
;
53 CodeTypeDeclaration codeTypeDeclaration
;
57 OperationBinding operationBinding
;
58 Message outputMessage
;
63 ServiceDescriptionImportWarnings warnings
= (ServiceDescriptionImportWarnings
)0;
64 ServiceDescriptionImporter descriptionImporter
;
66 XmlSchemas xmlSchemas
;
67 XmlSchemas soapSchemas
;
70 ArrayList asyncTypes
= new ArrayList ();
77 protected ProtocolImporter ()
81 #endregion // Constructors
86 public XmlSchemas AbstractSchemas
{
87 get { return descriptionImporter.Schemas; }
90 public Binding Binding
{
91 get { return binding; }
94 public string ClassName
{
95 get { return className; }
98 public CodeIdentifiers ClassNames
{
99 get { return classNames; }
102 public CodeNamespace CodeNamespace
{
103 get { return codeNamespace; }
106 public CodeTypeDeclaration CodeTypeDeclaration
{
107 get { return codeTypeDeclaration; }
111 public XmlSchemas ConcreteSchemas
{
112 get { return descriptionImporter.Schemas; }
115 public Message InputMessage
{
116 get { return inputMessage; }
119 public string MethodName
{
120 get { return methodName; }
123 public Operation Operation
{
124 get { return operation; }
127 public OperationBinding OperationBinding
{
128 get { return operationBinding; }
131 public Message OutputMessage
{
132 get { return outputMessage; }
139 public PortType PortType
{
140 get { return portType; }
143 public abstract string ProtocolName
{
147 public XmlSchemas Schemas
{
148 get { return descriptionImporter.Schemas; }
151 public Service Service
{
152 get { return service; }
155 public ServiceDescriptionCollection ServiceDescriptions
{
156 get { return descriptionImporter.ServiceDescriptions; }
159 public ServiceDescriptionImportStyle Style
{
160 get { return descriptionImporter.Style; }
163 public ServiceDescriptionImportWarnings Warnings
{
164 get { return warnings; }
165 set { warnings = value; }
168 internal ImportInfo ImportInfo
170 get { return iinfo; }
173 internal XmlSchemas LiteralSchemas
175 get { return xmlSchemas; }
178 internal XmlSchemas EncodedSchemas
180 get { return soapSchemas; }
184 internal CodeGenerationOptions CodeGenerationOptions
{
185 get { return descriptionImporter.CodeGenerationOptions; }
188 internal ICodeGenerator CodeGenerator
{
189 get { return descriptionImporter.CodeGenerator; }
192 internal ImportContext ImportContext
{
193 get { return descriptionImporter.Context; }
197 #endregion // Properties
201 internal bool Import (ServiceDescriptionImporter descriptionImporter
, CodeNamespace codeNamespace
, CodeCompileUnit codeCompileUnit
, ArrayList importInfo
)
203 this.descriptionImporter
= descriptionImporter
;
204 this.classNames
= new CodeIdentifiers();;
205 this.codeNamespace
= codeNamespace
;
206 this.codeCompileUnit
= codeCompileUnit
;
208 warnings
= (ServiceDescriptionImportWarnings
) 0;
212 ClasifySchemas (importInfo
);
216 foreach (ImportInfo info
in importInfo
)
218 foreach (Service service
in info
.ServiceDescription
.Services
)
220 this.service
= service
;
221 int bindingCount
= 0;
222 foreach (Port port
in service
.Ports
)
224 binding
= ServiceDescriptions
.GetBinding (port
.Binding
);
225 if (IsBindingSupported ()) bindingCount
++;
228 foreach (Port port
in service
.Ports
)
232 binding
= ServiceDescriptions
.GetBinding (port
.Binding
);
233 if (!IsBindingSupported ()) continue;
236 ImportPortBinding (bindingCount
> 1);
243 // Looks like MS.NET generates classes for all bindings if
244 // no services are present
246 foreach (ImportInfo info
in importInfo
)
249 foreach (Binding b
in info
.ServiceDescription
.Bindings
)
254 if (!IsBindingSupported ()) continue;
256 ImportPortBinding (true);
263 if (!found
) warnings
= ServiceDescriptionImportWarnings
.NoCodeGenerated
;
267 void ImportPortBinding (bool multipleBindings
)
270 if (multipleBindings
) className
= port
.Name
;
271 else className
= service
.Name
;
274 className
= binding
.Name
;
276 className
= classNames
.AddUnique (CodeIdentifier
.MakeValid (className
), port
);
277 className
= className
.Replace ("_x0020_", ""); // MS.NET seems to do this
281 portType
= ServiceDescriptions
.GetPortType (binding
.Type
);
282 if (portType
== null) throw new Exception ("Port type not found: " + binding
.Type
);
284 CodeTypeDeclaration codeClass
= BeginClass ();
285 codeTypeDeclaration
= codeClass
;
286 AddCodeType (codeClass
, port
!= null ? port
.Documentation
: null);
287 codeClass
.Attributes
= MemberAttributes
.Public
;
289 if (service
!= null && service
.Documentation
!= null && service
.Documentation
!= "")
290 AddComments (codeClass
, service
.Documentation
);
292 if (Style
== ServiceDescriptionImportStyle
.Client
) {
293 CodeAttributeDeclaration att
= new CodeAttributeDeclaration ("System.Diagnostics.DebuggerStepThroughAttribute");
294 AddCustomAttribute (codeClass
, att
, true);
296 att
= new CodeAttributeDeclaration ("System.ComponentModel.DesignerCategoryAttribute");
297 att
.Arguments
.Add (GetArg ("code"));
298 AddCustomAttribute (codeClass
, att
, true);
301 codeClass
.TypeAttributes
= System
.Reflection
.TypeAttributes
.Abstract
| System
.Reflection
.TypeAttributes
.Public
;
303 if (binding
.Operations
.Count
== 0) {
304 warnings
|= ServiceDescriptionImportWarnings
.NoMethodsGenerated
;
308 foreach (OperationBinding oper
in binding
.Operations
)
310 operationBinding
= oper
;
311 operation
= FindPortOperation ();
312 if (operation
== null) throw new Exception ("Operation " + operationBinding
.Name
+ " not found in portType " + PortType
.Name
);
314 foreach (OperationMessage omsg
in operation
.Messages
)
316 Message msg
= ServiceDescriptions
.GetMessage (omsg
.Message
);
317 if (msg
== null) throw new Exception ("Message not found: " + omsg
.Message
);
319 if (omsg
is OperationInput
)
325 CodeMemberMethod method
= GenerateMethod ();
329 methodName
= method
.Name
;
330 if (operation
.Documentation
!= null && operation
.Documentation
!= "")
331 AddComments (method
, operation
.Documentation
);
333 if (Style
== ServiceDescriptionImportStyle
.Client
)
334 AddAsyncMembers (method
.Name
, method
);
340 if (Style
== ServiceDescriptionImportStyle
.Client
)
346 catch (InvalidOperationException ex
)
348 warnings
|= ServiceDescriptionImportWarnings
.NoCodeGenerated
;
349 UnsupportedBindingWarning (ex
.Message
);
353 Operation
FindPortOperation ()
355 string inMessage
= null;
356 string outMessage
= null;
359 if (operationBinding
.Input
== null) throw new InvalidOperationException ("Input operation binding not found");
360 inMessage
= (operationBinding
.Input
.Name
!= null) ? operationBinding
.Input
.Name
: operationBinding
.Name
;
362 if (operationBinding
.Output
!= null) {
363 outMessage
= (operationBinding
.Output
.Name
!= null) ? operationBinding
.Output
.Name
: operationBinding
.Name
;
367 string operName
= operationBinding
.Name
;
369 Operation foundOper
= null;
370 foreach (Operation oper
in PortType
.Operations
)
372 if (oper
.Name
== operName
)
375 foreach (OperationMessage omsg
in oper
.Messages
)
377 if (omsg
is OperationInput
&& GetOperMessageName (omsg
, operName
) == inMessage
) hits
++;
378 if (omsg
is OperationOutput
&& GetOperMessageName (omsg
, operName
) == outMessage
) hits
++;
380 if (hits
== numMsg
) return oper
;
387 string GetOperMessageName (OperationMessage msg
, string operName
)
389 if (msg
.Name
== null) return operName
;
390 else return msg
.Name
;
393 internal void GenerateServiceUrl (string location
, CodeStatementCollection stms
)
395 if (ImportInfo
.AppSettingUrlKey
== null || ImportInfo
.AppSettingUrlKey
== string.Empty
) {
396 if (location
!= null) {
397 CodeExpression ce
= new CodeFieldReferenceExpression (new CodeThisReferenceExpression(), "Url");
398 CodeAssignStatement cas
= new CodeAssignStatement (ce
, new CodePrimitiveExpression (location
));
404 CodeExpression prop
= new CodePropertyReferenceExpression (new CodeTypeReferenceExpression ("System.Configuration.ConfigurationSettings"), "AppSettings");
405 prop
= new CodeIndexerExpression (prop
, new CodePrimitiveExpression (ImportInfo
.AppSettingUrlKey
));
406 stms
.Add (new CodeVariableDeclarationStatement (typeof(string), "urlSetting", prop
));
408 CodeExpression urlSetting
= new CodeVariableReferenceExpression ("urlSetting");
409 CodeExpression thisUrl
= new CodeFieldReferenceExpression (new CodeThisReferenceExpression(), "Url");
411 CodeStatement
[] trueStms
= new CodeStatement
[1];
412 CodeExpression ce
= urlSetting
;
413 CodeExpression cond
= new CodeBinaryOperatorExpression (urlSetting
, CodeBinaryOperatorType
.IdentityInequality
, new CodePrimitiveExpression (null));
415 if (ImportInfo
.AppSettingBaseUrl
!= null)
416 ce
= new CodeMethodInvokeExpression (new CodeTypeReferenceExpression (typeof(string)), "Concat", ce
, new CodePrimitiveExpression (ImportInfo
.AppSettingBaseUrl
));
417 trueStms
[0] = new CodeAssignStatement (thisUrl
, ce
);
419 if (location
!= null) {
420 CodeStatement
[] falseStms
= new CodeStatement
[1];
421 falseStms
[0] = new CodeAssignStatement (thisUrl
, new CodePrimitiveExpression (location
));
422 stms
.Add (new CodeConditionStatement (cond
, trueStms
, falseStms
));
425 stms
.Add (new CodeConditionStatement (cond
, trueStms
));
429 void ClasifySchemas (ArrayList importInfo
)
431 // I don't like this, but I could not find any other way of clasifying
432 // schemas between encoded and literal.
434 xmlSchemas
= new XmlSchemas ();
435 soapSchemas
= new XmlSchemas ();
437 foreach (ImportInfo info
in importInfo
)
439 foreach (Service service
in info
.ServiceDescription
.Services
)
441 foreach (Port port
in service
.Ports
)
445 binding
= ServiceDescriptions
.GetBinding (port
.Binding
);
446 if (binding
== null) continue;
447 portType
= ServiceDescriptions
.GetPortType (binding
.Type
);
448 if (portType
== null) continue;
450 foreach (OperationBinding oper
in binding
.Operations
)
452 operationBinding
= oper
;
453 operation
= FindPortOperation ();
454 if (operation
== null) continue;
456 foreach (OperationMessage omsg
in operation
.Messages
)
458 Message msg
= ServiceDescriptions
.GetMessage (omsg
.Message
);
459 if (msg
== null) continue;
461 if (omsg
is OperationInput
)
467 if (GetMessageEncoding (oper
.Input
) == SoapBindingUse
.Encoded
)
468 AddMessageSchema (soapSchemas
, oper
.Input
, inputMessage
);
470 AddMessageSchema (xmlSchemas
, oper
.Input
, inputMessage
);
472 if (oper
.Output
!= null) {
473 if (GetMessageEncoding (oper
.Output
) == SoapBindingUse
.Encoded
)
474 AddMessageSchema (soapSchemas
, oper
.Output
, outputMessage
);
476 AddMessageSchema (xmlSchemas
, oper
.Output
, outputMessage
);
483 XmlSchemas defaultList
= xmlSchemas
;
485 if (xmlSchemas
.Count
== 0 && soapSchemas
.Count
> 0)
486 defaultList
= soapSchemas
;
488 // Schemas not referenced by any message
489 foreach (XmlSchema sc
in Schemas
)
491 if (!soapSchemas
.Contains (sc
) && !xmlSchemas
.Contains (sc
)) {
492 if (ImportsEncodedNamespace (sc
))
493 soapSchemas
.Add (sc
);
495 defaultList
.Add (sc
);
500 void AddMessageSchema (XmlSchemas schemas
, MessageBinding mb
, Message msg
)
502 foreach (MessagePart part
in msg
.Parts
)
504 if (part
.Element
!= XmlQualifiedName
.Empty
)
505 AddIncludingSchema (schemas
, part
.Element
.Namespace
);
506 else if (part
.Type
!= XmlQualifiedName
.Empty
)
507 AddIncludingSchema (schemas
, part
.Type
.Namespace
);
509 SoapBodyBinding sbb
= mb
.Extensions
.Find (typeof(SoapBodyBinding
)) as SoapBodyBinding
;
510 if (sbb
!= null) AddIncludingSchema (schemas
, sbb
.Namespace
);
513 void AddIncludingSchema (XmlSchemas list
, string ns
)
515 XmlSchema sc
= Schemas
[ns
];
516 if (sc
== null || list
.Contains (sc
)) return;
518 foreach (XmlSchemaObject ob
in sc
.Includes
)
520 XmlSchemaImport import
= ob
as XmlSchemaImport
;
521 if (import
!= null) AddIncludingSchema (list
, import
.Namespace
);
525 SoapBindingUse
GetMessageEncoding (MessageBinding mb
)
527 SoapBodyBinding sbb
= mb
.Extensions
.Find (typeof(SoapBodyBinding
)) as SoapBodyBinding
;
530 if (mb
is InputBinding
) return SoapBindingUse
.Encoded
;
531 else return SoapBindingUse
.Literal
;
534 if (sbb
.Use
== SoapBindingUse
.Encoded
) return SoapBindingUse
.Encoded
;
536 return SoapBindingUse
.Literal
;
539 bool ImportsEncodedNamespace (XmlSchema sc
)
541 foreach (XmlSchemaObject ob
in sc
.Includes
)
543 XmlSchemaImport import
= ob
as XmlSchemaImport
;
544 if (import
.Namespace
== SoapProtocolReflector
.EncodingNamespace
) return true;
551 void AddAsyncTypes ()
553 foreach (CodeTypeDeclaration type
in asyncTypes
)
554 codeNamespace
.Types
.Add (type
);
558 void AddAsyncMembers (string messageName
, CodeMemberMethod method
)
560 CodeThisReferenceExpression ethis
= new CodeThisReferenceExpression();
561 CodePrimitiveExpression enull
= new CodePrimitiveExpression (null);
563 CodeMemberField codeField
= new CodeMemberField (typeof(System
.Threading
.SendOrPostCallback
), messageName
+ "OperationCompleted");
564 codeField
.Attributes
= MemberAttributes
.Private
;
565 CodeTypeDeclaration
.Members
.Add (codeField
);
567 // Event arguments class
569 string argsClassName
= classNames
.AddUnique (messageName
+ "CompletedEventArgs", null);
570 CodeTypeDeclaration argsClass
= new CodeTypeDeclaration (argsClassName
);
571 argsClass
.BaseTypes
.Add (new CodeTypeReference ("System.ComponentModel.AsyncCompletedEventArgs"));
573 CodeMemberField resultsField
= new CodeMemberField (typeof(object[]), "results");
574 resultsField
.Attributes
= MemberAttributes
.Private
;
575 argsClass
.Members
.Add (resultsField
);
577 CodeConstructor cc
= new CodeConstructor ();
578 cc
.Attributes
= MemberAttributes
.Assembly
;
579 cc
.Parameters
.Add (new CodeParameterDeclarationExpression (typeof(object[]), "results"));
580 cc
.Parameters
.Add (new CodeParameterDeclarationExpression (typeof(System
.Exception
), "exception"));
581 cc
.Parameters
.Add (new CodeParameterDeclarationExpression (typeof(bool), "cancelled"));
582 cc
.Parameters
.Add (new CodeParameterDeclarationExpression (typeof(object), "userState"));
583 cc
.BaseConstructorArgs
.Add (new CodeVariableReferenceExpression ("exception"));
584 cc
.BaseConstructorArgs
.Add (new CodeVariableReferenceExpression ("cancelled"));
585 cc
.BaseConstructorArgs
.Add (new CodeVariableReferenceExpression ("userState"));
586 CodeExpression thisResults
= new CodeFieldReferenceExpression (ethis
, "results");
587 cc
.Statements
.Add (new CodeAssignStatement (thisResults
, new CodeVariableReferenceExpression ("results")));
588 argsClass
.Members
.Add (cc
);
592 if (method
.ReturnType
.BaseType
!= "System.Void")
593 argsClass
.Members
.Add (CreateArgsProperty (method
.ReturnType
, "Result", ind
++));
595 foreach (CodeParameterDeclarationExpression par
in method
.Parameters
)
597 if (par
.Direction
== FieldDirection
.Out
|| par
.Direction
== FieldDirection
.Ref
)
598 argsClass
.Members
.Add (CreateArgsProperty (par
.Type
, par
.Name
, ind
++));
601 bool needsArgsClass
= (ind
> 0);
603 asyncTypes
.Add (argsClass
);
605 argsClassName
= "System.ComponentModel.AsyncCompletedEventArgs";
607 // Event delegate type
609 CodeTypeDelegate delegateType
= new CodeTypeDelegate (messageName
+ "CompletedEventHandler");
610 delegateType
.Parameters
.Add (new CodeParameterDeclarationExpression (typeof(object), "sender"));
611 delegateType
.Parameters
.Add (new CodeParameterDeclarationExpression (argsClassName
, "args"));
615 CodeMemberEvent codeEvent
= new CodeMemberEvent ();
616 codeEvent
.Name
= messageName
+ "Completed";
617 codeEvent
.Type
= new CodeTypeReference (delegateType
.Name
);
618 CodeTypeDeclaration
.Members
.Add (codeEvent
);
620 // Async method (without user state param)
622 CodeMemberMethod am
= new CodeMemberMethod ();
623 am
.Attributes
= MemberAttributes
.Public
| MemberAttributes
.Final
;
624 am
.Name
= method
.Name
+ "Async";
625 am
.ReturnType
= new CodeTypeReference (typeof(void));
626 CodeMethodInvokeExpression inv
;
627 inv
= new CodeMethodInvokeExpression (ethis
, am
.Name
);
628 am
.Statements
.Add (inv
);
630 // On...Completed method
632 CodeMemberMethod onCompleted
= new CodeMemberMethod ();
633 onCompleted
.Name
= "On" + messageName
+ "Completed";
634 onCompleted
.Attributes
= MemberAttributes
.Private
| MemberAttributes
.Final
;
635 onCompleted
.ReturnType
= new CodeTypeReference (typeof(void));
636 onCompleted
.Parameters
.Add (new CodeParameterDeclarationExpression (typeof(object), "arg"));
638 CodeConditionStatement anIf
= new CodeConditionStatement ();
640 CodeExpression eventField
= new CodeEventReferenceExpression (ethis
, codeEvent
.Name
);
641 anIf
.Condition
= new CodeBinaryOperatorExpression (eventField
, CodeBinaryOperatorType
.IdentityInequality
, enull
);
642 CodeExpression castedArg
= new CodeCastExpression (typeof(System
.Web
.Services
.Protocols
.InvokeCompletedEventArgs
), new CodeVariableReferenceExpression ("arg"));
643 CodeStatement invokeArgs
= new CodeVariableDeclarationStatement (typeof(System
.Web
.Services
.Protocols
.InvokeCompletedEventArgs
), "invokeArgs", castedArg
);
644 anIf
.TrueStatements
.Add (invokeArgs
);
646 CodeDelegateInvokeExpression delegateInvoke
= new CodeDelegateInvokeExpression ();
647 delegateInvoke
.TargetObject
= eventField
;
648 delegateInvoke
.Parameters
.Add (ethis
);
649 CodeObjectCreateExpression argsInstance
= new CodeObjectCreateExpression (argsClassName
);
650 CodeExpression invokeArgsVar
= new CodeVariableReferenceExpression ("invokeArgs");
651 if (needsArgsClass
) argsInstance
.Parameters
.Add (new CodeFieldReferenceExpression (invokeArgsVar
, "Results"));
652 argsInstance
.Parameters
.Add (new CodeFieldReferenceExpression (invokeArgsVar
, "Error"));
653 argsInstance
.Parameters
.Add (new CodeFieldReferenceExpression (invokeArgsVar
, "Cancelled"));
654 argsInstance
.Parameters
.Add (new CodeFieldReferenceExpression (invokeArgsVar
, "UserState"));
655 delegateInvoke
.Parameters
.Add (argsInstance
);
656 anIf
.TrueStatements
.Add (delegateInvoke
);
658 onCompleted
.Statements
.Add (anIf
);
662 CodeMemberMethod asyncMethod
= new CodeMemberMethod ();
663 asyncMethod
.Attributes
= MemberAttributes
.Public
| MemberAttributes
.Final
;
664 asyncMethod
.Name
= method
.Name
+ "Async";
665 asyncMethod
.ReturnType
= new CodeTypeReference (typeof(void));
667 CodeExpression delegateField
= new CodeFieldReferenceExpression (ethis
, codeField
.Name
);
668 anIf
= new CodeConditionStatement ();
669 anIf
.Condition
= new CodeBinaryOperatorExpression (delegateField
, CodeBinaryOperatorType
.IdentityEquality
, enull
);;
670 CodeExpression delegateRef
= new CodeMethodReferenceExpression (ethis
, onCompleted
.Name
);
671 CodeExpression newDelegate
= new CodeObjectCreateExpression (typeof(System
.Threading
.SendOrPostCallback
), delegateRef
);
672 CodeAssignStatement cas
= new CodeAssignStatement (delegateField
, newDelegate
);
673 anIf
.TrueStatements
.Add (cas
);
674 asyncMethod
.Statements
.Add (anIf
);
676 CodeArrayCreateExpression paramsArray
= new CodeArrayCreateExpression (typeof(object));
680 CodeIdentifiers paramsIds
= new CodeIdentifiers ();
682 foreach (CodeParameterDeclarationExpression par
in method
.Parameters
)
684 paramsIds
.Add (par
.Name
, null);
685 if (par
.Direction
== FieldDirection
.In
|| par
.Direction
== FieldDirection
.Ref
) {
686 CodeParameterDeclarationExpression inpar
= new CodeParameterDeclarationExpression (par
.Type
, par
.Name
);
687 am
.Parameters
.Add (inpar
);
688 asyncMethod
.Parameters
.Add (inpar
);
689 inv
.Parameters
.Add (new CodeVariableReferenceExpression (par
.Name
));
690 paramsArray
.Initializers
.Add (new CodeVariableReferenceExpression (par
.Name
));
695 inv
.Parameters
.Add (enull
);
697 string userStateName
= paramsIds
.AddUnique ("userState", null);
698 asyncMethod
.Parameters
.Add (new CodeParameterDeclarationExpression (typeof(object), userStateName
));
700 CodeExpression userStateVar
= new CodeVariableReferenceExpression (userStateName
);
701 asyncMethod
.Statements
.Add (BuildInvokeAsync (messageName
, paramsArray
, delegateField
, userStateVar
));
703 CodeTypeDeclaration
.Members
.Add (am
);
704 CodeTypeDeclaration
.Members
.Add (asyncMethod
);
705 CodeTypeDeclaration
.Members
.Add (onCompleted
);
707 asyncTypes
.Add (delegateType
);
710 CodeMemberProperty
CreateArgsProperty (CodeTypeReference type
, string name
, int ind
)
712 CodeMemberProperty prop
= new CodeMemberProperty ();
713 prop
.Attributes
= MemberAttributes
.Public
| MemberAttributes
.Final
;
718 CodeThisReferenceExpression ethis
= new CodeThisReferenceExpression();
719 CodeExpression thisResults
= new CodeFieldReferenceExpression (ethis
, "results");
720 prop
.GetStatements
.Add (new CodeMethodInvokeExpression (ethis
, "RaiseExceptionIfNecessary"));
721 CodeArrayIndexerExpression arrValue
= new CodeArrayIndexerExpression (thisResults
, new CodePrimitiveExpression (ind
));
722 CodeExpression retval
= new CodeCastExpression (type
, arrValue
);
723 prop
.GetStatements
.Add (new CodeMethodReturnStatement (retval
));
727 internal virtual CodeExpression
BuildInvokeAsync (string messageName
, CodeArrayCreateExpression paramsArray
, CodeExpression delegateField
, CodeExpression userStateVar
)
729 CodeThisReferenceExpression ethis
= new CodeThisReferenceExpression();
730 CodeMethodInvokeExpression inv2
= new CodeMethodInvokeExpression (ethis
, "InvokeAsync");
731 inv2
.Parameters
.Add (new CodePrimitiveExpression (messageName
));
732 inv2
.Parameters
.Add (paramsArray
);
733 inv2
.Parameters
.Add (delegateField
);
734 inv2
.Parameters
.Add (userStateVar
);
740 public void AddExtensionWarningComments (CodeCommentStatementCollection comments
, ServiceDescriptionFormatExtensionCollection extensions
)
742 throw new NotImplementedException ();
745 protected abstract CodeTypeDeclaration
BeginClass ();
747 protected virtual void BeginNamespace ()
751 protected virtual void EndClass ()
755 protected virtual void EndNamespace ()
759 protected abstract CodeMemberMethod
GenerateMethod ();
760 protected abstract bool IsBindingSupported ();
761 protected abstract bool IsOperationFlowSupported (OperationFlow flow
);
764 public Exception
OperationBindingSyntaxException (string text
)
766 throw new NotImplementedException ();
770 public Exception
OperationSyntaxException (string text
)
772 throw new NotImplementedException ();
775 public void UnsupportedBindingWarning (string text
)
777 warnings
|= ServiceDescriptionImportWarnings
.UnsupportedBindingsIgnored
;
778 AddGlobalComments ("WARNING: Could not generate proxy for binding " + binding
.Name
+ ". " + text
);
781 public void UnsupportedOperationBindingWarning (string text
)
783 warnings
|= ServiceDescriptionImportWarnings
.UnsupportedOperationsIgnored
;
784 AddGlobalComments ("WARNING: Could not generate operation " + OperationBinding
.Name
+ ". " + text
);
787 public void UnsupportedOperationWarning (string text
)
789 warnings
|= ServiceDescriptionImportWarnings
.UnsupportedOperationsIgnored
;
790 AddGlobalComments ("WARNING: Could not generate operation " + OperationBinding
.Name
+ ". " + text
);
793 void AddGlobalComments (string comments
)
795 codeNamespace
.Comments
.Add (new CodeCommentStatement (comments
, false));
798 void AddComments (CodeTypeMember member
, string comments
)
800 if (comments
== null || comments
== "") member
.Comments
.Add (new CodeCommentStatement ("<remarks/>", true));
801 else member
.Comments
.Add (new CodeCommentStatement ("<remarks>\n" + comments
+ "\n</remarks>", true));
804 void AddCodeType (CodeTypeDeclaration type
, string comments
)
806 AddComments (type
, comments
);
807 codeNamespace
.Types
.Add (type
);
810 internal void AddCustomAttribute (CodeTypeMember ctm
, CodeAttributeDeclaration att
, bool addIfNoParams
)
812 if (att
.Arguments
.Count
== 0 && !addIfNoParams
) return;
814 if (ctm
.CustomAttributes
== null) ctm
.CustomAttributes
= new CodeAttributeDeclarationCollection ();
815 ctm
.CustomAttributes
.Add (att
);
818 internal void AddCustomAttribute (CodeTypeMember ctm
, string name
, params CodeAttributeArgument
[] args
)
820 if (ctm
.CustomAttributes
== null) ctm
.CustomAttributes
= new CodeAttributeDeclarationCollection ();
821 ctm
.CustomAttributes
.Add (new CodeAttributeDeclaration (name
, args
));
824 internal CodeAttributeArgument
GetArg (string name
, object value)
826 return new CodeAttributeArgument (name
, new CodePrimitiveExpression(value));
829 internal CodeAttributeArgument
GetEnumArg (string name
, string enumType
, string enumValue
)
831 return new CodeAttributeArgument (name
, new CodeFieldReferenceExpression (new CodeTypeReferenceExpression(enumType
), enumValue
));
834 internal CodeAttributeArgument
GetArg (object value)
836 return new CodeAttributeArgument (new CodePrimitiveExpression(value));
839 internal CodeAttributeArgument
GetTypeArg (string name
, string typeName
)
841 return new CodeAttributeArgument (name
, new CodeTypeOfExpression(typeName
));