An application with plugins has been obtained that creates the WCF program contract programmatically, and then connects it to the plugin interfaces, however, it is difficult for them to figure out how to get the generated contract for reusing the types found in DLL plugins.
Does anyone know how to configure a ServiceContractGenerator to reuse types in specific assemblies?
This is what I use to create the atm contract code:
public Assembly CreateProxy(String url)
{
MetadataExchangeClient mexClient = new MetadataExchangeClient(new Uri(url + "/mex"), MetadataExchangeClientMode.MetadataExchange);
mexClient.ResolveMetadataReferences = true;
MetadataSet metaDocs = mexClient.GetMetadata();
WsdlImporter importer = new WsdlImporter(metaDocs);
ServiceContractGenerator generator = new ServiceContractGenerator();
generator.NamespaceMappings.Add("*", "NameSpace123");
Collection<ContractDescription> contracts = importer.ImportAllContracts();
ServiceEndpointCollection endpoints = importer.ImportAllEndpoints();
foreach (ContractDescription contract in contracts)
generator.GenerateServiceContractType(contract);
if (generator.Errors.Count != 0)
throw new Exception("There were errors during code compilation.");
CodeDomProvider codeDomProvider = CodeDomProvider.CreateProvider("C#");
CompilerParameters parameters = new CompilerParameters();
parameters.CompilerOptions = string.Format(@" /lib:{0}", "\"C:\\Program Files\\Reference Assemblies\\Microsoft\\Framework\\v3.0\"");
parameters.ReferencedAssemblies.Add("System.ServiceModel.dll");
parameters.ReferencedAssemblies.Add("System.Runtime.Serialization.dll");
parameters.GenerateExecutable = false;
parameters.GenerateInMemory = true;
parameters.IncludeDebugInformation = true;
parameters.OutputAssembly = "WCFGenerated.dll";
CodeCompileUnit codeUnit = generator.TargetCompileUnit;
CompilerResults results = codeDomProvider.CompileAssemblyFromDom(parameters, codeUnit);
foreach (CompilerError oops in results.Errors)
throw new Exception("Compilation Error Creating Assembly: " + oops.ErrorText);
return Assembly.LoadFile(Directory.GetCurrentDirectory() + "\\WCFGenerated.dll");
}
Edit: I never got this to work correctly, however I managed to load exe as an assembly and use it to create a proxy:
try
{
Thread.CurrentThread.CurrentUICulture = CultureInfo.CurrentUICulture.GetConsoleFallbackUICulture();
if (Console.OutputEncoding.CodePage != Encoding.UTF8.CodePage && Console.OutputEncoding.CodePage != Thread.CurrentThread.CurrentUICulture.TextInfo.OEMCodePage)
{
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
}
var assembly = Assembly.LoadFile(Path.Combine(info.TempDir, SVCUTIL_EXE));
var optionsType = assembly.GetType("Microsoft.Tools.ServiceModel.SvcUtil.Options");
var runtimeType = assembly.GetType("Microsoft.Tools.ServiceModel.SvcUtil.ToolRuntime");
var options = optionsType.InvokeMember("ParseArguments", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { info.Args });
ConstructorInfo c = runtimeType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { optionsType }, null);
var runtime = c.Invoke(new Object[] { options });
var exitCode = (int)runtimeType.InvokeMember("Run", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, null, runtime, null);
if (exitCode != 0)
throw new Exception(String.Format("Failed to generate wcf contract code [Bad Result: {0}]", exitCode));
}
catch (Exception e)
{
if (e is TargetInvocationException)
e = e.InnerException;
info.E = e;
}
Lodle source
share