2012-05-18 16 views
5

erhielt eine APP mit Plug-ins, die die WCF-Client Vertrag programmatisch erzeugt und hakt es dann zu den Plugins Schnittstellen auf, aber im, kämpfen, um herauszufinden, wie die erzeugte Vertrag bekommen Arten wiederzuverwenden in den DLLs des Plugins gefunden.Re-Use-Typen bei der Generierung von WCF-Client Vertrag Programmatically

Hat jemand wissen, wie die ServiceContractGenerator Setup-Typen in bestimmten Baugruppen wieder zu verwenden?

Dies ist, was ich benutze den Vertrag Code atm zu generieren:

 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); 

     //Must load it like this otherwise the assembly wont match the one used for the generated code below 
     return Assembly.LoadFile(Directory.GetCurrentDirectory() + "\\WCFGenerated.dll"); 
    } 

Edit: Ich habe nie ganz richtig zu arbeiten, verwalten ich habe aber die exe als Baugruppe zu laden und verwenden zu erzeugen der 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"); 

      //Options option = Options.ParseArguments(args); 
      var options = optionsType.InvokeMember("ParseArguments", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { info.Args }); 

      //ToolRuntime toolRuntime = new ToolRuntime(option); 
      ConstructorInfo c = runtimeType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { optionsType }, null); 
      var runtime = c.Invoke(new Object[] { options }); 

      //var runtime = Activator.CreateInstance(runtimeType, , null, options); 

      //toolRuntime.Run(); 
      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; 
     } 
+1

Was ist die Frage hier? – MrWuf

+0

Bearbeitet, um Frage hinzuzufügen – Lodle

Antwort

1

Wenn die Assembly Sie Arten von wiederverwenden möchten, wird durch den Webservice Vertrag tatsächlich verwendet wird, dann Zugabe es genau wie @peer vorgeschlagen sollte wahrscheinlich funktionieren! Alle SVCutil sollten eine Reference Option haben, was zu dem passt, was er gesagt hat. Wenn dies nicht der Fall ist, denkt svcutil.exe, dass der Typ "A" aus der Assembly und der Typ "A" aus dem Service nicht identisch sind. Entweder gibt es feine Unterschiede in den Namen oder Namespaces oder - in den XML-Namespaces (oder Schemas sind tatsächlich unterschiedlich).

überprüfen Sie bitte "Reuse existing types" is ignored when adding a service reference - Ich meine, stellen Sie sicher, dass die 'vorhandenen Typen' in der 'vorhandenen Assembly' wirklich auf das gleiche Schema Realm zugeordnet sind. Beachten Sie, dass dieses Vertragsattribut innerhalb dieser Assembly sein muss, die die Typen definiert! Wenn es deins ist, füge einfach hinzu und kompiliere neu.

auch, haben Sie versucht, Svcutil manuell in der Konsole ausgeführt? Sie werden wahrscheinlich einige zusätzliche Fehler/Warnungen dort bekommen, vielleicht werden sie aufzeigen, was das eigentliche Problem ist.

5

Wie Sie bereits wissen, unterstützt Svcutil diese Option (/ Referenzflag). so alles, was Sie brauchen, ist svcutil.exe Reflektor zu öffnen und die gleichen wie diese Methode tun: Microsoft.Tools.ServiceModel.SvcUtil.ImportModule + InitializationHelper.InitReferencedContracts

internal static void InitReferencedContracts(Options options, WsdlImporter importer, ServiceContractGenerator contractGenerator) 
{ 
    foreach (Type type in options.ReferencedTypes) 
    { 
     if (type.IsDefined(typeof(ServiceContractAttribute), false)) 
     { 
      try 
      { 
       ContractDescription contract = ContractDescription.GetContract(type); 
       XmlQualifiedName key = new XmlQualifiedName(contract.Name, contract.Namespace); 
       importer.KnownContracts.Add(key, contract); 
       contractGenerator.ReferencedTypes.Add(contract, type); 
       continue; 
      } 
      catch (Exception exception) 
      { 
       if (Tool.IsFatal(exception)) 
       { 
        throw; 
       } 
       throw new ToolRuntimeException(SR.GetString("ErrUnableToLoadReferenceType", new object[] { type.AssemblyQualifiedName }), exception); 
      } 
     } 
    } 
} 
+0

Sah scvutil aber sah das nicht. Werde es versuchen. Vielen Dank – Lodle