2009-08-10 Atsushi Enomoto <atsushi@ximian.com>
authorAtsushi Eno <atsushieno@gmail.com>
Mon, 10 Aug 2009 11:38:23 +0000 (11:38 -0000)
committerAtsushi Eno <atsushieno@gmail.com>
Mon, 10 Aug 2009 11:38:23 +0000 (11:38 -0000)
* ServiceContractGenerator.cs,
  OperationContractGenerationContext.cs : support extensions i.e.
  IServiceContractGenerationExtension and IOperation...(ditto) .

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

mcs/class/System.ServiceModel/System.ServiceModel.Description/ChangeLog
mcs/class/System.ServiceModel/System.ServiceModel.Description/OperationContractGenerationContext.cs
mcs/class/System.ServiceModel/System.ServiceModel.Description/ServiceContractGenerator.cs

index 90212204ba76dc0b57319570752888f9ed3e8b60..c4601a5d119db3cc576e5a820e666cb41175894d 100644 (file)
@@ -1,3 +1,9 @@
+2009-08-10  Atsushi Enomoto  <atsushi@ximian.com>
+
+       * ServiceContractGenerator.cs,
+         OperationContractGenerationContext.cs : support extensions i.e.
+         IServiceContractGenerationExtension and IOperation...(ditto) .
+
 2009-08-10  Atsushi Enomoto  <atsushi@ximian.com>
 
        * ServiceContractGenerator.cs : first step to add moonlight-based
index 841cf56d9aaa1c237cd9687c4c7691218ec143c9..274a2be62be773633fde11e04d6763c3161419a5 100644 (file)
@@ -44,7 +44,7 @@ namespace System.ServiceModel.Description
                        CodeTypeDeclaration declaringType,
                        CodeMemberMethod method)
                        : this (serviceContractGenerator, contract, operation,
-                               declaringType, false, method, null)
+                               declaringType, method, null, null)
                {
                }
 
@@ -53,38 +53,24 @@ namespace System.ServiceModel.Description
                        ServiceContractGenerationContext contract,
                        OperationDescription operation,
                        CodeTypeDeclaration declaringType,
+                       CodeMemberMethod method,
                        CodeMemberMethod beginMethod,
                        CodeMemberMethod endMethod)
-                       : this (serviceContractGenerator, contract, operation,
-                               declaringType, true, beginMethod, endMethod)
-               {
-               }
-
-               private OperationContractGenerationContext (
-                       ServiceContractGenerator serviceContractGenerator,
-                       ServiceContractGenerationContext contract,
-                       OperationDescription operation,
-                       CodeTypeDeclaration declaringType,
-                       bool isAsync,
-                       CodeMemberMethod method, // sync
-                       CodeMemberMethod endMethod) // async
                {
                        generator = serviceContractGenerator;
                        this.contract = contract;
                        this.operation = operation;
                        declaring_type = declaringType;
                        this.method = method;
+                       this.begin_method = beginMethod;
                        this.end_method = endMethod;
-                       is_async = isAsync;
                }
 
-               bool is_async;
                ServiceContractGenerator generator;
                ServiceContractGenerationContext contract;
                OperationDescription operation;
                CodeTypeDeclaration declaring_type;
-               CodeMemberMethod method;
-               CodeMemberMethod end_method;
+               CodeMemberMethod method, begin_method, end_method;
 
                public ServiceContractGenerator ServiceContractGenerator {
                        get { return generator; }
@@ -98,14 +84,17 @@ namespace System.ServiceModel.Description
                public CodeTypeDeclaration DeclaringType {
                        get { return declaring_type; }
                }
-               public CodeMemberMethod Method {
+               public CodeMemberMethod SyncMethod {
                        get { return method; }
                }
+               public CodeMemberMethod BeginMethod {
+                       get { return begin_method; }
+               }
                public CodeMemberMethod EndMethod {
                        get { return end_method; }
                }
                public bool IsAsync {
-                       get { return is_async; }
+                       get { return begin_method != null; }
                }
        }
 }
index d668dfd1a89eb579f96bc5d7090042ed229fc6d6..a6db1ae6d7ef964aebef38f72de8366eedbd5f19 100644 (file)
@@ -55,6 +55,7 @@ namespace System.ServiceModel.Description
                        = new Dictionary<ContractDescription,Type> ();
                ServiceContractGenerationOptions options;
                Dictionary<QName, QName> imported_names = null;
+               ServiceContractGenerationContext contract_context;
 
                public ServiceContractGenerator ()
                        : this (null, null)
@@ -130,15 +131,17 @@ namespace System.ServiceModel.Description
                {
                        CodeNamespace cns = GetNamespace (contractDescription.Namespace);
                        imported_names = new Dictionary<QName, QName> ();
-                       try {
-                               return ExportInterface (contractDescription, cns);
-                       } finally {
-                               if ((Options & ServiceContractGenerationOptions.ClientClass) != 0)
-                                       GenerateProxyClass (contractDescription, cns);
-
-                               if ((Options & ServiceContractGenerationOptions.ChannelInterface) != 0)
-                                       GenerateChannelInterface (contractDescription, cns);
-                       }
+                       var ret = ExportInterface (contractDescription, cns);
+
+                       // FIXME: handle duplex callback
+
+                       if ((Options & ServiceContractGenerationOptions.ChannelInterface) != 0)
+                               GenerateChannelInterface (contractDescription, cns);
+
+                       if ((Options & ServiceContractGenerationOptions.ClientClass) != 0)
+                               GenerateProxyClass (contractDescription, cns);
+
+                       return ret;
                }
 
                CodeNamespace GetNamespace (string ns)
@@ -178,6 +181,8 @@ namespace System.ServiceModel.Description
                        type.BaseTypes.Add (clientBase);
                        type.BaseTypes.Add (new CodeTypeReference (cd.Name));
 
+                       contract_context = new ServiceContractGenerationContext (this, cd, type);
+
                        // .ctor()
                        CodeConstructor ctor = new CodeConstructor ();
                        ctor.Attributes = MemberAttributes.Public;
@@ -245,6 +250,13 @@ namespace System.ServiceModel.Description
                        // Add channelbase
                        GenerateProxyChannelClass (cd, type, clientBase);
 #endif
+
+                       // add extensions
+                       foreach (var cb in cd.Behaviors) {
+                               var gex = cb as IServiceContractGenerationExtension;
+                               if (gex != null)
+                                       gex.GenerateContract (contract_context);
+                       }
                }
 
                void GenerateProxyChannelClass (ContractDescription cd, CodeTypeDeclaration parentClass, CodeTypeReference clientBaseType)
@@ -444,6 +456,8 @@ namespace System.ServiceModel.Description
                                // EndXxx() implementation
 
                                cm = new CodeMemberMethod ();
+                               cm.Attributes = MemberAttributes.Public 
+                                               | MemberAttributes.Final;
                                type.Members.Add (cm);
                                cm.Name = "End" + od.Name;
 
@@ -475,13 +489,17 @@ namespace System.ServiceModel.Description
 
                void AddImplementationChannelMethods (CodeTypeDeclaration type, ContractDescription cd)
                {
+                       CodeMemberMethod syncMethod = null, beginMethod = null, endMethod = null;
                        foreach (OperationDescription od in cd.Operations) {
                                CodeMemberMethod cm = new CodeMemberMethod ();
                                type.Members.Add (cm);
-                               if (GenerateAsync)
+                               if (GenerateAsync) {
                                        cm.Name = "Begin" + od.Name;
-                               else
+                                       beginMethod = cm;
+                               } else {
                                        cm.Name = od.Name;
+                                       syncMethod = cm;
+                               }
                                cm.Attributes = MemberAttributes.Public 
                                                | MemberAttributes.Final;
                                CodeTypeReference returnTypeFromMessageContract = null;
@@ -535,14 +553,19 @@ namespace System.ServiceModel.Description
                                        cm.Statements.Add (new CodeMethodReturnStatement (call));
 
                                // For async mode, add EndXxx() too.
-                               if (!GenerateAsync)
-                                       return;
+                               if (!GenerateAsync) {
+                                       ProcessOperationContextExtensions (od, type, syncMethod, null, null);
+                                       continue;
+                               }
 
                                // EndXxx() implementation
 
                                cm = new CodeMemberMethod ();
+                               cm.Attributes = MemberAttributes.Public 
+                                               | MemberAttributes.Final;
                                type.Members.Add (cm);
                                cm.Name = "End" + od.Name;
+                               endMethod = cm;
 
                                var res = new CodeParameterDeclarationExpression (new CodeTypeReference (typeof (IAsyncResult)), "result");
                                cm.Parameters.Add (res);
@@ -572,6 +595,21 @@ namespace System.ServiceModel.Description
                                        cm.Statements.Add (new CodeExpressionStatement (call));
                                else
                                        cm.Statements.Add (new CodeMethodReturnStatement (call));
+
+                               ProcessOperationContextExtensions (od, type, syncMethod, beginMethod, endMethod);
+                       }
+               }
+
+               void ProcessOperationContextExtensions (OperationDescription od, CodeTypeDeclaration type, CodeMemberMethod sync, CodeMemberMethod begin, CodeMemberMethod end)
+               {
+                       OperationContractGenerationContext octx = null;
+                       foreach (var ob in od.Behaviors) {
+                               var gex = ob as IOperationContractGenerationExtension;
+                               if (gex == null)
+                                       continue;
+                               if (octx == null)
+                                       octx = new OperationContractGenerationContext (this, contract_context, od, type, sync, begin, end);
+                               gex.GenerateOperation (octx);
                        }
                }
 
@@ -616,7 +654,7 @@ namespace System.ServiceModel.Description
                {
                        throw new NotImplementedException ();
                }
-               
+
                private void ExportDataContract (XmlTypeMapping mapping)
                {
                        if (mapping == null)