2010-04-12 2 views
5

ricevo il seguente errore quando invoco un oggetto personalizzato
"Object of type 'customObject' cannot be converted to type 'customObject'."oggetto di tipo 'customObject' non può essere convertito nel tipo 'customObject'

seguito è lo scenario quando sono ottenere questo errore:

  • Invoco un metodo in una DLL dinamicamente.
  • caricare un assembly
  • CreateInstance ....

Quando si chiama MethodInfo.Invoke() passando int, string come parametro per il mio metodo funziona bene => Non ci sono eccezioni sono gettati.

Ma se provo a passare uno dei miei oggetti classe personalizzati come parametro, ottengo un'eccezione ArgumentException e non è né ArgumentOutOfRangeExceptionArgumentNullException.

"Object of type 'customObject' cannot be converted to type 'customObject'."

sto facendo questo in un'applicazione web.

Il file di classe contenente il metodo si trova in un progetto diverso. Anche l'oggetto personalizzato è una classe separata nello stesso file.

Non esiste una cosa chiamata static assembly nel mio codice. Sto cercando di invocare un metodo web in modo dinamico. questo webmethod sta avendo il tipo CustomObject come parametro di input. Quindi quando invoco il webmethod sto creando dinamicamente l'assembly proxy e tutto. Dallo stesso assembly sto provando a creare un'istanza dell'oggetto cusotm asserendo i valori alle sue proprietà e quindi passando questo oggetto come parametro e invocando il metodo. tutto è dinamico e nulla si crea statica .. :(

di riferimento aggiuntivo non viene utilizzato. seguito è un codice di esempio ho provato a crearlo

public static object CallWebService(string webServiceAsmxUrl, string serviceName, string methodName, object[] args) 
    { 
     System.Net.WebClient client = new System.Net.WebClient(); 
     //-Connect To the web service 
     using (System.IO.Stream stream = client.OpenRead(webServiceAsmxUrl + "?wsdl")) 
     { 
      //--Now read the WSDL file describing a service. 
      ServiceDescription description = ServiceDescription.Read(stream); 
      ///// LOAD THE DOM ///////// 
      //--Initialize a service description importer. 
      ServiceDescriptionImporter importer = new ServiceDescriptionImporter(); 
      importer.ProtocolName = "Soap12"; // Use SOAP 1.2. 
      importer.AddServiceDescription(description, null, null); 
      //--Generate a proxy client. importer.Style = ServiceDescriptionImportStyle.Client; 
      //--Generate properties to represent primitive values. 
      importer.CodeGenerationOptions = System.Xml.Serialization.CodeGenerationOptions.GenerateProperties; 
      //--Initialize a Code-DOM tree into which we will import the service. 
      CodeNamespace nmspace = new CodeNamespace(); 
      CodeCompileUnit unit1 = new CodeCompileUnit(); 
      unit1.Namespaces.Add(nmspace); 
      //--Import the service into the Code-DOM tree. This creates proxy code 
      //--that uses the service. 
      ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit1); 
      if (warning == 0) //--If zero then we are good to go 
      { 
       //--Generate the proxy code 
       CodeDomProvider provider1 = CodeDomProvider.CreateProvider("CSharp"); 
       //--Compile the assembly proxy with the appropriate references 
       string[] assemblyReferences = new string[5] { "System.dll", "System.Web.Services.dll", "System.Web.dll", "System.Xml.dll", "System.Data.dll" }; 
       CompilerParameters parms = new CompilerParameters(assemblyReferences); 
       CompilerResults results = provider1.CompileAssemblyFromDom(parms, unit1); 
       //-Check For Errors 
       if (results.Errors.Count > 0) 
       { 
        StringBuilder sb = new StringBuilder(); 
        foreach (CompilerError oops in results.Errors) 
        { 
         sb.AppendLine("========Compiler error============"); 
         sb.AppendLine(oops.ErrorText); 
        } 
        throw new System.ApplicationException("Compile Error Occured calling webservice. " + sb.ToString()); 
       } 
       //--Finally, Invoke the web service method 
       Type foundType = null; 
       Type[] types = results.CompiledAssembly.GetTypes(); 
       foreach (Type type in types) 
       { 
        if (type.BaseType == typeof(System.Web.Services.Protocols.SoapHttpClientProtocol)) 
        { 
         Console.WriteLine(type.ToString()); 
         foundType = type; 
        } 
       } 

       object wsvcClass = results.CompiledAssembly.CreateInstance(foundType.ToString()); 
       MethodInfo mi = wsvcClass.GetType().GetMethod(methodName); 
       return mi.Invoke(wsvcClass, args); 
      } 
      else 
      { 
       return null; 
      } 
     } 
    } 

io non riesco a trovare nulla static in quello che ho fare.

Qualsiasi aiuto è molto apprezzato.

saluti, Phani Kumar fotovoltaici

+0

* Perché * lo faresti? Perché non solo "aggiungi riferimento web" al progetto? – Aaronaught

+0

Sto sviluppando un'applicazione in cui l'URL WSDL è necessario per richiamare un metodo web in esso. come dovrei usare diversi metodi web non posso fare un riferimento web. –

risposta

2

Hai esaminato l'aspetto generato dalla classe proxy? Non è necessario il prefisso per chiamare un servizio Web. Basta creare una classe che eredita da SoapHttpClientProtocol e chiamare Invoke (methodName, params).

Stai rendendo questo molto più complicato del necessario. Onestamente.

EDIT Se si crea una classe come questa:

public class SoapClient : SoapHttpClientProtocol 
{ 

    public SoapClient() 
    { 

    } 

    public object[] Invoke(string method, object[] args) 
    { 
     return base.Invoke(method, args); 
    } 

} 

e chiamare in questo modo:

SoapClient soapClient = new SoapClient(); 
soapClient.Url = webServiceAsmxUrl; 
soapClient.Invoke(methodName, args); 

Penso che si vedrà che esso ha gli stessi risultati esatti come quello stai facendo.

+0

Ho esaminato il codice condiviso nel collegamento. Sembra che possa essere utilizzato quando sono disponibili le informazioni sugli spazi dei nomi dei metodi webservice e web. Ma nell'applicazione che sto attualmente sviluppando otterrò l'URL di wdsl in modo dinamico e verrà modificato di conseguenza. in questo scenario l'approccio specificato nell'URL specificato non risolverà il mio problema. per favore fatemi sapere se ho preso nella direzione sbagliata. –

+0

Ho aggiornato la mia risposta con un esempio di codice per spiegare di cosa sto parlando. –

+0

Sì, questa risposta è corretta. L'unico motivo per cui è necessario compilare il codice del servizio Web è se è necessario eseguire il controllo del tipo di compilazione in base a un URL del servizio Web noto. Sei già in fase di esecuzione quando invochi questo, quindi non ti va bene. – ZeroBugBounce

2

Lasciatemi provare a spiegare la ragione più probabile che il problema abbia nel mio approccio.

Quando ho richiamato un metodo nell'assembly chiamato "methodname" nel webservice sto provando a passare i parametri richiesti per questo come args [] alla funzione "CallWebService" Questo argomento [] quando passato sarà eseguito correttamente funziona quando provo a passare parametri normali come i tipi primitivi inclusa la stringa.

Ma questo è quello che ho fatto quando ho provato a passare un oggetto personalizzato come parametro.

Tre cose che sono fatte in questo.

  1. creare un oggetto di quel tipo all'esterno della funzione CallWebService (utilizzando la riflessione). quando ho fatto in quel modo, ciò che accade è un'istanza dell'oggetto personalizzato creato internamente con un nome di dll temporaneo.
  2. dopo aver impostato il set delle proprietà dell'oggetto e inviarlo alla funzione CallWebService come oggetto nell'array args.
  3. Mi sono stancato di creare un'istanza del servizio web creando la DLL dinamica.

    oggetto wsvcClass = results.CompiledAssembly.CreateInstance (foundType.ToString());

Quando finalmente provato a richiamare il metodo con l'istanza del complesso dinamico creato ho cercato di passare la customobject creato nel passo 1,2 con struttura args.

al momento dell'invocazione il CLR tenta di verificare se l'oggetto personalizzato passato come input e il metodo che viene richiamato provengono dalla stessa DLL.

che evidentemente non dipende dal modo in cui viene eseguita l'implementazione.

Quindi segue è l'approccio che deve essere utilizzato per superare il problema ho bisogno per creare l'assembly oggetto personalizzato con la stessa assemblea che ho usato per la creare l'istanza webservice ..

ho implementato completamente questo approccio e ha funzionato bene

MethodInfo m = type.GetMethod(methodName); 
ParameterInfo[] pm = m.GetParameters(); 
object ob; 
object[] y = new object[1]; 
foreach (ParameterInfo paraminfo in pm) 
{ 
    ob = this.webServiceAssembly.CreateInstance(paraminfo.ParameterType.Name); 

    //Some Junk Logic to get the set the values to the properties of the custom Object 
    foreach (PropertyInfo propera in ob.GetType().GetProperties()) 
    { 
     if (propera.Name == "AppGroupid") 
     { 
      propera.SetValue(ob, "SQL2005Tools", null); 
     } 
     if (propera.Name == "Appid") 
     { 
      propera.SetValue(ob, "%", null); 
     } 
    } 
    y[0] = ob; 
} 
0

Questo è un thread vecchio, ma ho appena avuto un problema simile. Ho guardato qui, questo è apparso, ma non ho visto soluzioni utili.

L'errore dell'OP era questo: L'oggetto di tipo 'customObject' non può essere convertito in tipo 'customObject'.

Il mio errore molto simile era questo: L'oggetto di tipo "System.String" non può essere convertito in tipo "System.Windows.Forms.AccessibleRole".

Ecco come ho risolto il mio problema:

ho eseguito un Trova e sostituisci (uso CRTL + SHIFT + F per portare la finestra di dialogo verso l'alto) di ricerca nel corrente Progetto per il termine AccessibleRole.

Find and Replace dialog

all'interno di uno dei designer del Form era un posto in cui mi è stato l'assegnazione di un valore a una variabile AccessibleRoleString utilizzando ToString().

Ho risolto questo problema e il mio problema è andato via.

Spero che questo aiuti gli altri.

1

ciò può verificarsi quando la versione di una DLL a cui si fa riferimento nel codice riflesso è diversa dalla versione di tale dll nel codice compilato.