Search code examples
c#arraysobjectcopying

Copy array of objects to array of different type


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 ?


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