2009-03-24 9 views
1

Früher lief ich in ein Problem versucht, eine Typdefinition zwischen meinem ASMX webservice zu teilen und meiner ASPX-Seite (Webclient)Kopieren Array von Objekten Array von einer anderen Typ

Confused on C# Array of objects and implicit type conversion

Wie ich das verstehen Hinweis: Das "Problem", das dadurch entsteht, kann gelöst werden, indem das im Client erstellte Array von Objekten in ein neues Array von Objekten kopiert wird, wie es von der ASMX-Proxy-Klasse definiert wird.

Als Rookie in C# kämpfe ich immer noch mit dieser einfachen Aufgabe. Hier mehr Teile meines Codes sind (die anderen Fragmente in der früheren Post bleiben unverändert):

... hier ist, wo ich die „Testdaten“ bevölkern ich an den Webdienst übergeben möchten:

// create an array of MetaData objects 
MetaData[] nvPairs = new MetaData[20]; // arbitrary length of 20 pairs 

// create arbitrary MetaData objects in the array 
nvPairs[0] = new MetaData("Grant Number", "2577-9912"); 
nvPairs[1] = new MetaData("OPEAnalyst", "Simpson"); 

... hier versuche ich, eine Funktion definiert „Kopie“ von „echtem“ Typ in meinem TRIMBrokerUtil Namespace (die ich nicht vollständig, weil der Proxy verwenden) an die Proxy-Version dieses Typs:

protected TRIMBrokerASMXProxy.ASMXProxy.MetaData[] CopyMetaData(
    MetaData utilArray) 
{ 
    TRIMBrokerASMXProxy.ASMXProxy.MetaData[] outArray = 
     new TRIMBrokerASMXProxy.ASMXProxy.MetaData[utilArray.Name.Length]; 
    int i; 
    for (i = 0; i < utilArray.Name.Length; i++) 
    { 
     outArray[i].Name = utilArray.Name; 
     outArray[i].Value = utilArray.Value; 
    } 
    return outArray; 
} 

... und dann hier ist, wo ich versuche, diese Funktion aufzurufen (Compiler markiert 2 Fehler auf diesem lin e:

TRIMBrokerASMXProxy.ASMXProxy.MetaData[] kvData = 
    CopyMetaData(metaDataArray); 

Beide der Kompilierung Fehler unter Punkt auf der gleichen Linie:

Fehler 1 Die beste überladene Methode Spiel für ‚_Default.CopyMetaData (TRIMBrokerUtil.MetaData)‘ einige ungültige Argumente hat

Fehler 2 Argument '1': Konvertierung von 'TRIMBrokerUtil.MetaData []' zu 'TRIMBrokerUtil.MetaData' nicht möglich

Bin ich in der Nähe?

Antwort

6

Sie haben Ihren Parameter als MetaData und nicht als MetaData[] deklariert - mit anderen Worten, es ist kein Array. Sie verwenden dann eher utilArray.Name, aber es ist nicht klar warum.

ich Sie eigentlich vermuten möchte:

protected TRIMBrokerASMXProxy.ASMXProxy.MetaData[] 
    CopyMetaData(MetaData[] utilArray) 
{ 
    TRIMBrokerASMXProxy.ASMXProxy.MetaData[] outArray = 
     new TRIMBrokerASMXProxy.ASMXProxy.MetaData[utilArray.Length]; 
    for (int i = 0; i < utilArray.Length; i++) 
    { 
     outArray[i] = new TRIMBrokerASMXProxy.ASMXProxy.MetaData(); 
     outArray[i].Name = utilArray[i].Name; 
     outArray[i].Value = utilArray[i].Value; 
    } 
    return outArray; 
} 

By the way, Sie könnten eine using Richtlinie zu prüfen, diese leichter zu lesen:

using ProxyMetaData = TRIMBrokerASMXProxy.ASMXProxy.MetaData; 

... 

protected ProxyMetaData[] CopyMetaData(MetaData[] utilArray) 
{ 
    ProxyMetaData[] outArray = new ProxyMetaData[utilArray.Length]; 
    for (int i = 0; i < utilArray.Length; i++) 
    { 
     outArray[i] = new ProxyMetaData(); 
     outArray[i].Name = utilArray[i].Name; 
     outArray[i].Value = utilArray[i].Value; 
    } 
    return outArray; 
} 

Eine weitere Alternative ist Array.ConvertAll:

ProxyMetaData[] output = Array.ConvertAll(input, 
    metaData => new ProxyMetaData(metaData.Name, metaData.Value)); 

Wenn Sie nicht C# 3 verwenden, können Sie uns e eine anonyme Methode dafür.Wenn ProxyMetaData keinen geeigneten Konstruktor haben und Sie sind mit C# 3, können Sie ein Objekt initializer verwenden:

ProxyMetaData[] output = Array.ConvertAll(input, 
    metaData => new ProxyMetaData { metaData.Name, metaData.Value }); 

Wenn Sie mit C# 2 und ohne entsprechende Konstruktor stecken, dann:

ProxyMetaData[] output = Array.ConvertAll(input, delegate(MetaData metaData) 
{ 
    ProxyMetaData proxy = new ProxyMetaData(); 
    proxy.Name = metaData.Name; 
    proxy.Value = metaData.Value; 
}); 

ich denken, dass alle Grundlagen abgedeckt ist :)

+0

Alle hageln König Jon .. + 1. Eine kurze Frage, ich mag es, die Liste zu verwenden und dann mit ToArray() zurückzukehren. Ich benutze gerne Listen, da ich keine Indizes wie i verwende. Töte ich die Performance, indem ich das tue? – Perpetualcoder

+0

Nun, Sie sind Leistung, aber wahrscheinlich nicht signifikant. Wenn ich von einem Array * zu * einem Array konvertiere, würde ich wahrscheinlich nicht über eine Liste gehen, aber sobald es irgendwelche Zweifel über die Länge des Endergebnisses gibt, werde ich eine Liste für die Bequemlichkeit verwenden. Vergessen Sie nicht Array.ConvertAll obwohl :) –

+0

Wow! Wo ist das Trinkgeldglas? Du bist ein Heiliger und so gut, um mir so zu helfen. Ich lerne langsam und ich danke dir wirklich für deine freundliche Hilfe. –

2

ich würde LINQ einfach, dies zu tun:

TRIMBrokerASMXProxy.ASMXProxy.MetaData[] kvData = 
    metaDataArray.Select(d => 
     new TRIMBrokerASMXProxy.ASMXProxy.MetaData(
      d.Name, d.Value)).ToArray(); 

Wenn Sie .NET 3.5 verwenden, bedeutet dies auch, dass Sie WCF ebenfalls verwenden können, was Sie zum Generieren des Proxys verwenden sollten. Sie könnten Ihren TRIMBrokerASMXProxy.ASMXProxy.MetaData-Typ mit dem DataContract-Attribut und den Mitgliedern, die serialisiert werden, mit dem DataMember-Attribut versehen. Dann könnten Sie Ihren Vertrag mit dem tatsächlichen Typ definieren und müssen keine Conversion durchführen.

+0

Also würde ich, aber ich bin mir nicht sicher, ob ich das einem C# Rookie vorschlagen würde, besonders wenn wir nicht wissen, ob er .NET 3.5 verwendet oder nicht :) –

+0

Ich habe gerade den gleichen Code eingegeben, bevor SO dazu aufgefordert wurde dass eine neue Antwort geschrieben wurde :) +1 – Perpetualcoder

+0

@Jon geben Sie vielleicht die Anfängermotivation, um mit Sachen zu beschleunigen :) – Perpetualcoder

0

Sie können auch Array.ConvertAll verwenden. Ich weiß, dass Sie relativ neu dazu sind, also lassen Sie mich versuchen zu erklären. Es hat 2 generische Parameter. Der erste ist der Typ des Arrays, den es konvertieren will (nennen wir es I). Und der zweite Typ, in den Sie konvertieren möchten (nennen wir es O). Es akzeptiert ein Array vom Typ I und gibt ein Array vom Typ O zurück. Der zweite Parameter ist ein Converter-Delegat. Anwenden der Namensgebung wir haben seine Signatur wie.

delegate O Converter(I input); 

Der Text des Delegaten muss den Code enthalten, der für die Konvertierung erforderlich ist. In der ConvertAll-Funktion wird der Code durch jeden der Werte im Eingabearray durchlaufen und dann an den Delegaten übergeben. Der vom Delegat zurückgegebene Wert wird dann in einem Ausgabearray gespeichert. Nachdem alle Werte konvertiert wurden, wird das Ausgabearray an den Benutzer zurückgegeben.

using ProxyMetaData = TRIMBrokerASMXProxy.ASMXProxy.MetaData; 

ProxyMetaData[] convertedArray = Array.ConvertAll<MetaData, ProxyMetaData>(utilArray, 
delegate(MetaData metaData) 
{ 
    ProxyMetaData returnValue = new ProxyMetaData(); 
    returnValue.Name = metaData.Name; 
    returnValue.Value = metaData.Value; 
    return returnValue; 
}); 
+0

Danke Jake. Das macht Sinn und ich werde versuchen, aber mit Jons Methode stieß ich auf eine weitere Wendung und versuchte meine Proxy-Klasse neu aufzubauen: TRIMBrokerUtil.MetaData kann nicht serialisiert werden, da es keinen parameterlosen Konstruktor hat Noch brauche ich einen Konstruktor mit 2 Params; 1 für den Namen, 1 für den Wert –

+0

Wenn ich richtig verstehe, würde ich die gleiche Beschwerde mit Array.ConvertAll auch laufen. Ich denke, ich bin vielleicht in ein "größeres" Problem geraten? –