2012-05-18 11 views
5

Masz aplikację z wtyczkami, która generuje kontrakt klienta WCF programowo, a następnie podłącza go do interfejsów wtyczek, jednak próbuję ustalić, jak uzyskać wygenerowany kontrakt do ponownego użycia typów znaleźć w plikach DLL wtyczki.Typy ponownego użycia podczas generowania kontraktu klienta WCF Programowo

Czy ktoś wie, jak skonfigurować ServiceContractGenerator do ponownego użycia typów w zdefiniowanych zestawach?

To co ja używać do generowania bankomatu kodu zamówienia:

 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: Nigdy nie miałem to działało całkiem dobrze, jednak udało mi się załadować exe jako zespół i używać do generowania 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

Jakie jest tutaj pytanie? – MrWuf

+0

Edytowane w celu dodania pytania – Lodle

Odpowiedz

1

Jeżeli montaż chcesz ponownie użyć typów z faktycznie wykorzystywane przez umowie WebService, a potem po prostu dodanie go jak @peer sugerowanej prawdopodobnie powinien pracować! wszystko, czego potrzebuje svcutil, to opcja/odniesienie, co odwzorowuje na to, co powiedział. jeśli nie, to svcutil.exe uważa, że ​​typ "A" z zestawu i typ "A" z usługi nie są takie same. Albo istnieje subtelna różnica w nazwach lub przestrzeniach nazw, albo - w przestrzeniach nazw XML (lub schematach są rzeczywiście różne).

Proszę sprawdzić "Reuse existing types" is ignored when adding a service reference - Mam na myśli, upewnij się, że "istniejące typy" w "istniejącym montażu" są rzeczywiście mapowane do tej samej sfery schematu. Pamiętaj, że ten atrybut kontraktu musi znajdować się wewnątrz tego zestawu, który definiuje typy! jeśli jest twój, po prostu dodaj i przekompiluj.

również, czy próbowałeś uruchomić svcutil ręcznie w konsoli? prawdopodobnie pojawi się tam kilka dodatkowych błędów/ostrzeżeń, być może wskażą, jaki jest faktyczny problem.

5

jak już wiesz, svcutil obsługuje tę opcję (/ flaga referencyjna). więc wszystko, co potrzebne jest, aby otworzyć svcutil.exe w reflektorze i tak samo jak tą metodą: 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

Spojrzałem na scvutil, ale nie widziałem tego. Spróbuję. Dzięki – Lodle

Powiązane problemy