Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/mcs/class
diff options
context:
space:
mode:
authorAtsushi Eno <atsushieno@gmail.com>2009-08-10 11:16:23 +0400
committerAtsushi Eno <atsushieno@gmail.com>2009-08-10 11:16:23 +0400
commit673080161033deffc91a30d8c6e201bdea6b14b6 (patch)
treec87c3a35537aaa94f9d8c243fa7df1a50323d29b /mcs/class
parent718f5f501469ba891a0959a9af91123a43e4b989 (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/ChangeLog6
-rw-r--r--mcs/class/System.ServiceModel/System.ServiceModel.Description/ServiceContractGenerator.cs140
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;