diff options
author | Atsushi Eno <atsushieno@gmail.com> | 2009-08-10 11:16:23 +0400 |
---|---|---|
committer | Atsushi Eno <atsushieno@gmail.com> | 2009-08-10 11:16:23 +0400 |
commit | 673080161033deffc91a30d8c6e201bdea6b14b6 (patch) | |
tree | c87c3a35537aaa94f9d8c243fa7df1a50323d29b /mcs/class | |
parent | 718f5f501469ba891a0959a9af91123a43e4b989 (diff) |
2009-08-10 Atsushi Enomoto <atsushi@ximian.com>
* ServiceContractGenerator.cs : first step to add moonlight-based
client proxy generator (it is not supported in 3.5. needs to be
enabled by some hook, such as reflection-based hack).
svn path=/trunk/mcs/; revision=139621
Diffstat (limited to 'mcs/class')
-rw-r--r-- | mcs/class/System.ServiceModel/System.ServiceModel.Description/ChangeLog | 6 | ||||
-rw-r--r-- | mcs/class/System.ServiceModel/System.ServiceModel.Description/ServiceContractGenerator.cs | 140 |
2 files changed, 144 insertions, 2 deletions
diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Description/ChangeLog b/mcs/class/System.ServiceModel/System.ServiceModel.Description/ChangeLog index b70143dfe71..90212204ba7 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Description/ChangeLog +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Description/ChangeLog @@ -1,3 +1,9 @@ +2009-08-10 Atsushi Enomoto <atsushi@ximian.com> + + * ServiceContractGenerator.cs : first step to add moonlight-based + client proxy generator (it is not supported in 3.5. needs to be + enabled by some hook, such as reflection-based hack). + 2009-08-07 Atsushi Enomoto <atsushi@ximian.com> * ContractDescription.cs : wcf & 2.1 is specially annoying land :( diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Description/ServiceContractGenerator.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Description/ServiceContractGenerator.cs index 4d79e7ed349..d668dfd1a89 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Description/ServiceContractGenerator.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Description/ServiceContractGenerator.cs @@ -239,7 +239,41 @@ namespace System.ServiceModel.Description type.Members.Add (ctor); // service contract methods - AddImplementationMethods (type, cd); + AddImplementationClientMethods (type, cd); + +#if ENABLE_MOONLIGHT_PROXY + // Add channelbase + GenerateProxyChannelClass (cd, type, clientBase); +#endif + } + + void GenerateProxyChannelClass (ContractDescription cd, CodeTypeDeclaration parentClass, CodeTypeReference clientBaseType) + { + string name = cd.Name + "Channel"; + if (name [0] == 'I') + name = name.Substring (1); + + var channelBase = new CodeTypeReference (typeof (ClientBase<>.ChannelBase<>)); + channelBase.TypeArguments.Add (clientBaseType.TypeArguments [0]); + channelBase.TypeArguments.Add (new CodeTypeReference (cd.Name)); + var type = new CodeTypeDeclaration (name); + parentClass.Members.Add (type); + type.TypeAttributes = TypeAttributes.Public; + type.BaseTypes.Add (channelBase); + type.BaseTypes.Add (new CodeTypeReference (cd.Name)); + + // .ctor(ClientBase<T> client) + var ctor = new CodeConstructor (); + ctor.Attributes = MemberAttributes.Public; + ctor.Parameters.Add ( + new CodeParameterDeclarationExpression ( + clientBaseType, "client")); + ctor.BaseConstructorArgs.Add ( + new CodeArgumentReferenceExpression ("client")); + type.Members.Add (ctor); + + // service contract methods + AddImplementationChannelMethods (type, cd); } void GenerateChannelInterface (ContractDescription cd, CodeNamespace cns) @@ -357,7 +391,7 @@ namespace System.ServiceModel.Description pi.Name)); } - void AddImplementationMethods (CodeTypeDeclaration type, ContractDescription cd) + void AddImplementationClientMethods (CodeTypeDeclaration type, ContractDescription cd) { foreach (OperationDescription od in cd.Operations) { CodeMemberMethod cm = new CodeMemberMethod (); @@ -439,6 +473,108 @@ namespace System.ServiceModel.Description } } + void AddImplementationChannelMethods (CodeTypeDeclaration type, ContractDescription cd) + { + foreach (OperationDescription od in cd.Operations) { + CodeMemberMethod cm = new CodeMemberMethod (); + type.Members.Add (cm); + if (GenerateAsync) + cm.Name = "Begin" + od.Name; + else + cm.Name = od.Name; + cm.Attributes = MemberAttributes.Public + | MemberAttributes.Final; + CodeTypeReference returnTypeFromMessageContract = null; + + List<CodeExpression> inArgs = new List<CodeExpression> (); + List<CodeExpression> outArgs = new List<CodeExpression> (); + + if (od.SyncMethod != null) { + // FIXME: shouldn't this be done as ExportMessage()? + ParameterInfo [] pars = od.SyncMethod.GetParameters (); + ExportParameters (cm, pars); + cm.ReturnType = new CodeTypeReference (od.SyncMethod.ReturnType); + int i = 0; + foreach (ParameterInfo pi in pars) { + if (pi.IsIn) + inArgs.Add (new CodeArgumentReferenceExpression (pi.Name)); + else if (pi.IsOut) + outArgs.Add (new CodeArgumentReferenceExpression (pi.Name)); + } + } else { + inArgs.AddRange (ExportMessages (od.Messages, cm, true)); + returnTypeFromMessageContract = cm.ReturnType; + if (GenerateAsync) { + AddBeginAsyncArgs (cm); + cm.ReturnType = new CodeTypeReference (typeof (IAsyncResult)); + } + } + + var argsDecl = new CodeVariableDeclarationStatement ( + typeof (object []), + "args", + new CodeArrayCreateExpression (typeof (object), inArgs.ToArray ())); + cm.Statements.Add (argsDecl); + + var args = new List<CodeExpression> (); + args.Add (new CodePrimitiveExpression (od.Name)); + args.Add (new CodeVariableReferenceExpression ("args")); + if (GenerateAsync) { + args.Add (new CodeArgumentReferenceExpression ("asyncCallback")); + args.Add (new CodeArgumentReferenceExpression ("userState")); + } + + CodeExpression call = new CodeMethodInvokeExpression ( + new CodeBaseReferenceExpression (), + "BeginInvoke", + args.ToArray ()); + + if (cm.ReturnType.BaseType == "System.Void") + cm.Statements.Add (new CodeExpressionStatement (call)); + else + cm.Statements.Add (new CodeMethodReturnStatement (call)); + + // For async mode, add EndXxx() too. + if (!GenerateAsync) + return; + + // EndXxx() implementation + + cm = new CodeMemberMethod (); + type.Members.Add (cm); + cm.Name = "End" + od.Name; + + var res = new CodeParameterDeclarationExpression (new CodeTypeReference (typeof (IAsyncResult)), "result"); + cm.Parameters.Add (res); + + if (od.SyncMethod != null) // FIXME: it depends on sync method! + cm.ReturnType = new CodeTypeReference (od.SyncMethod.ReturnType); + else + cm.ReturnType = returnTypeFromMessageContract; + + string resultArgName = "result"; + if (od.EndMethod != null) + resultArgName = od.EndMethod.GetParameters () [0].Name; + argsDecl = new CodeVariableDeclarationStatement ( + typeof (object []), + "args", + new CodeArrayCreateExpression (typeof (object), new CodePrimitiveExpression (outArgs.Count))); + cm.Statements.Add (argsDecl); + + call = new CodeMethodInvokeExpression ( + new CodeBaseReferenceExpression (), + "EndInvoke", + new CodePrimitiveExpression (od.Name), + new CodeVariableReferenceExpression ("args"), + new CodeArgumentReferenceExpression (resultArgName)); + + if (cm.ReturnType.BaseType == "System.Void") + cm.Statements.Add (new CodeExpressionStatement (call)); + else + cm.Statements.Add (new CodeMethodReturnStatement (call)); + } + } + private CodeExpression[] ExportMessages (MessageDescriptionCollection messages, CodeMemberMethod method, bool return_args) { CodeExpression [] args = null; |