Скопировать массив объектов в массив другого типа
Вопрос
Ранее я столкнулся с проблемой при попытке совместного использования определения типа между моим веб-сервисом ASMX и моей страницей .aspx (веб-клиентом).
Запутался в C#: Массив объектов и неявное преобразование типов
Насколько я понимаю совет, «проблему», которую это создает, можно решить путем копирования массива объектов, созданного в клиенте, в новый массив объектов, определенный прокси-классом ASMX.
Будучи новичком в C#, я все еще пытаюсь справиться с этой простой задачей.Вот еще части моего кода (остальные фрагменты в предыдущем посте остались неизменными):
...здесь я заполняю «тестовые данные», которые хочу передать веб-сервису:
// 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");
...здесь я пытаюсь функцию «скопировать» из «реального» типа, определенного в моем пространстве имен TRIMBrokerUtil (которое я не могу использовать полностью из-за прокси-сервера), в прокси-версию этого типа:
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;
}
...и вот здесь я пытаюсь вызвать эту функцию (компилятор отмечает 2 ошибки в этой строке:
TRIMBrokerASMXProxy.ASMXProxy.MetaData[] kvData =
CopyMetaData(metaDataArray);
Обе ошибки компиляции ниже указывают на одну и ту же строку:
Ошибка 1. Лучшее совпадение перегруженного метода для «_Default.CopyMetaData(TRIMBrokerUtil.MetaData)» имеет несколько недопустимых аргументов.
Ошибка 2. Аргумент «1»:невозможно преобразовать «TRIMBrokerUtil.MetaData[]» в «TRIMBrokerUtil.MetaData»
Я близко?
Решение
Вы объявили свой параметр как MetaData
скорее, чем MetaData[]
- другими словами, это не массив.Затем вы используете utilArray.Name
довольно много, но непонятно почему.
Я подозреваю, что вы действительно хотите:
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;
}
Кстати, возможно, вы захотите рассмотреть using
директива, чтобы облегчить чтение:
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;
}
Другой альтернативой является Array.ConvertAll
:
ProxyMetaData[] output = Array.ConvertAll(input,
metaData => new ProxyMetaData(metaData.Name, metaData.Value));
Если вы не используете C# 3, вы можете использовать для этого анонимный метод.Если ProxyMetaData
нет соответствующего конструктора, и вы являются используя С# 3, вы можете использовать инициализатор объекта:
ProxyMetaData[] output = Array.ConvertAll(input,
metaData => new ProxyMetaData { metaData.Name, metaData.Value });
Если вы застряли на C# 2 и у вас нет подходящего конструктора, то:
ProxyMetaData[] output = Array.ConvertAll(input, delegate(MetaData metaData)
{
ProxyMetaData proxy = new ProxyMetaData();
proxy.Name = metaData.Name;
proxy.Value = metaData.Value;
});
я думать это охватило все основы :)
Другие советы
Я бы просто использовал LINQ для этого:
TRIMBrokerASMXProxy.ASMXProxy.MetaData[] kvData =
metaDataArray.Select(d =>
new TRIMBrokerASMXProxy.ASMXProxy.MetaData(
d.Name, d.Value)).ToArray();
Кроме того, если вы используете .NET 3.5, это означает, что вы также можете использовать WCF, который вам следует использовать для создания прокси.Вы сможете присвоить тип TRIMBrokerASMXProxy.ASMXProxy.MetaData атрибуту DataContract, а сериализуемые элементы — атрибуту DataMember.Тогда вы сможете определить свой контракт с фактическим типом, и вам вообще не придется выполнять преобразование.
Вы также можете использовать Array.ConvertAll.Я знаю, что вы относительно новичок в этом, поэтому позвольте мне попытаться объяснить.Он имеет 2 общих параметра.Первый — это тип массива, который он хочет преобразовать (назовем его I).И второй тип, в который вы хотите преобразовать (назовем его O).Он принимает массив типа I и возвращает массив типа O.Второй параметр — делегат Converter.Применяя именование, мы получаем его подпись.
delegate O Converter(I input);
Тело делегата должно содержать код, необходимый для преобразования.Внутри функции ConvertAll код перебирает каждое значение входного массива и затем передает его делегату.Значение, возвращаемое делегатом, затем сохраняется в выходном массиве.Выходной массив возвращается пользователю после преобразования всех значений.
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;
});