Question

Previously, I ran into a problem trying to share a type definition between my ASMX webservice and my .aspx page (webclient)

Confused on C# Array of objects and implicit type conversion

As I understand the advice, the "problem" this creates can be solved by copying the array of objects created in the client to a new array of objects as defined by the ASMX proxy class.

Being a rookie in C# I am still struggling with this simple task. Here are more parts of my code (the other fragments in the previous post remain unchanged):

... here is where I populate the "test data" I want to pass to the web service:

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

... here I attempt a function to "copy" from "real" type defined in my TRIMBrokerUtil namespace (which I can't use completely because of the proxy) to the proxy version of that type:

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

... and then here is where I try to call that function (compiler flags 2 errors on this line:

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

Both of the compile errors below point to the same line:

Error 1 The best overloaded method match for '_Default.CopyMetaData(TRIMBrokerUtil.MetaData)' has some invalid arguments

Error 2 Argument '1': cannot convert from 'TRIMBrokerUtil.MetaData[]' to 'TRIMBrokerUtil.MetaData'

Am I close ?

Was it helpful?

Solution

You've declared your parameter to be MetaData rather than MetaData[] - in other words it's not an array. You're then using utilArray.Name rather a lot, but it's not clear why.

I suspect you actually want:

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, you might want to consider a using directive to make this easier to read:

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

Another alternative is Array.ConvertAll:

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

If you're not using C# 3 you can use an anonymous method for that. If ProxyMetaData doesn't have an appropriate constructor and you are using C# 3, you can use an object initializer:

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

If you're stuck with C# 2 and no appropriate constructor, then:

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

I think that's covered all the bases :)

OTHER TIPS

I would just use LINQ to do this:

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

Additionally, if you are using .NET 3.5, it means you can use WCF as well, which is what you should be using to generate the proxy. You would be able to attribute your TRIMBrokerASMXProxy.ASMXProxy.MetaData type with the DataContract attribute and the members being serialized with the DataMember attribute. Then, you would be able to define your contract with the actual type, and not have to perform conversion at all.

You can also use Array.ConvertAll. I know youre relatively new to this so let me try to explain. It has 2 generic parameters. The first one being the type of the array it wants to convert(lets call it I). And the second one the type you want to convert to (lets call it O). It accepts an array of type I and returns an array of type O. The second parameter is a Converter delegate. Applying the naming we have its signature goes like.

delegate O Converter(I input);

The body of the delegate must contain the code necessary to do the conversion. Inside the ConvertAll function, the code iterates thru each of the values in the input array and passes then to the delegate. The value returned by the delegate is then stored into an output array. The output array is returned to the user once all values are converted.

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;
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top