1: using System;
2: using System.Collections.Generic;
3: using System.Linq;
4: using System.ServiceModel;
5: using System.ServiceModel.Description;
6: using System.Globalization;
7: using System.Collections.ObjectModel;
8: using System.CodeDom.Compiler;
9:
10: namespace Client
11: { 12: class Program
13: { 14: static void Main(string[] args)
15: { 16: // Define the metadata address, contract name, operation name, and parameters.
17: // You can choose between MEX endpoint and HTTP GET by changing the address and enum value.
18: Uri mexAddress = new Uri("http://localhost:8732/CalculatorService/?wsdl"); 19: // For MEX endpoints use a MEX address and a mexMode of .MetadataExchange
20: MetadataExchangeClientMode mexMode = MetadataExchangeClientMode.HttpGet;
21: string contractName = "ICalculator";
22: string operationName = "Add";
23: object[] operationParameters = new object[] { 1, 2 }; 24:
25: // Get the metadata file from the service.
26: MetadataExchangeClient mexClient = new MetadataExchangeClient(mexAddress, mexMode);
27: mexClient.ResolveMetadataReferences = true;
28: MetadataSet metaSet = mexClient.GetMetadata();
29:
30: // Import all contracts and endpoints
31: WsdlImporter importer = new WsdlImporter(metaSet);
32: Collection<ContractDescription> contracts = importer.ImportAllContracts();
33: ServiceEndpointCollection allEndpoints = importer.ImportAllEndpoints();
34:
35: // Generate type information for each contract
36: ServiceContractGenerator generator = new ServiceContractGenerator();
37: var endpointsForContracts = new Dictionary<string, IEnumerable<ServiceEndpoint>>();
38:
39: foreach (ContractDescription contract in contracts)
40: { 41: generator.GenerateServiceContractType(contract);
42: // Keep a list of each contract's endpoints
43: endpointsForContracts[contract.Name] = allEndpoints.Where(
44: se => se.Contract.Name == contract.Name).ToList();
45: }
46:
47: if (generator.Errors.Count != 0)
48: throw new Exception("There were errors during code compilation."); 49:
50: // Generate a code file for the contracts
51: CodeGeneratorOptions options = new CodeGeneratorOptions();
52: options.BracingStyle = "C";
53: CodeDomProvider codeDomProvider = CodeDomProvider.CreateProvider("C#"); 54:
55: // Compile the code file to an in-memory assembly
56: // Don't forget to add all WCF-related assemblies as references
57: CompilerParameters compilerParameters = new CompilerParameters(
58: new string[] { 59: "System.dll", "System.ServiceModel.dll",
60: "System.Runtime.Serialization.dll" });
61: compilerParameters.GenerateInMemory = true;
62:
63: CompilerResults results = codeDomProvider.CompileAssemblyFromDom(
64: compilerParameters, generator.TargetCompileUnit);
65:
66: if (results.Errors.Count > 0)
67: { 68: throw new Exception("There were errors during generated code compilation"); 69: }
70: else
71: { 72: // Find the proxy type that was generated for the specified contract
73: // (identified by a class that implements the contract and ICommunicationbject)
74: Type clientProxyType = results.CompiledAssembly.GetTypes().First(
75: t => t.IsClass &&
76: t.GetInterface(contractName) != null &&
77: t.GetInterface(typeof(ICommunicationObject).Name) != null);
78:
79: // Get the first service endpoint for the contract
80: ServiceEndpoint se = endpointsForContracts[contractName].First();
81:
82: // Create an instance of the proxy
83: // Pass the endpoint's binding and address as parameters
84: // to the ctor
85: object instance = results.CompiledAssembly.CreateInstance(
86: clientProxyType.Name,
87: false,
88: System.Reflection.BindingFlags.CreateInstance,
89: null,
90: new object[] { se.Binding, se.Address }, 91: CultureInfo.CurrentCulture, null);
92:
93: // Get the operation's method, invoke it, and get the return value
94: object retVal = instance.GetType().GetMethod(operationName).
95: Invoke(instance, operationParameters);
96:
97: Console.WriteLine(retVal.ToString());
98: }
99: }
100: }
101: }