В рамках моего проекта я пытаюсь создать веб-интерфейс, в котором пользователь выбирает метод и передает значения. Моя программа должна иметь возможность динамически вызывать метод и создавать список параметров во время выполнения, чтобы передать его методу.
Я создал разделенный запятыми список (строку) пар ключ и значение. Эта пара ключ / значение - не что иное, как имя параметра и значение моего метода (имя метода хранится в переменной). Пример: string params = "ID:123;Name:Garry;Address:addressObject;AddressLine:108 Plaza Lane;City:Avenel;State:NJ;Zip:07001;"
. Где ID и Имя - это простые строковые переменные, а Адрес - это пользовательский тип. То, что следует за Address, т.е. AddressLine, City, State и Zip, является элементами объекта Address. И мое определение метода
public string GetInfo(string ID, string Name, Address addressObject)
{
//return something;
}
Я динамически вызываю метод (GetInfo), который хранится в переменной sMethodName, используя DynamicProxy, например:
string sMethodName = "GetInfo";
object result = (object) proxy.CallMethod(sMethodName, arguments);
Проблема в том, как передать список аргументов динамически? До сих пор я просто могу извлечь значения из переменной csv в NamedValueCollection. Вот код:
public static void StoreParameterValues(string param)
{
nvc = new NameValueCollection();
param = param.TrimEnd(';');
string[] parameters = param.Split(new char[] { ';' });
foreach (string val in parameters)
{
string[] keyValue = val.Split(new char[] { ':' });
nvc.Add(keyValue[0], keyValue[1]);
}
}
.. а вот код, который пытается построить параметр:
string methodName = "GetInfo";
DynamicProxyFactory factory = new DynamicProxyFactory("http://../myservice.svc");
string sContract = "";
foreach (ServiceEndpoint endpoint in factory.Endpoints)
{
sContract = endpoint.Contract.Name;
}
DynamicProxy proxy = factory.CreateProxy(sContract);
string[] values = null;
// Create the parameter list
object[] arguments = new object[nvc.Count];
int i = -1;
foreach (string key in nvc.Keys)
{
values = nvc.GetValues(key);
foreach (string value in values)
{
arguments[++i] = value;
}
}
object result = (object) proxy.CallMethod(methodName, arguments);
Приведенный выше код работает, если у меня есть простые примитивные типы, но я не уверен, как я могу построить логику для любых других пользовательских типов. Как я могу создать объект динамически типа, хранящегося в переменной? Не уверен, смог ли я правильно задать свой вопрос. Я надеюсь на это:)
Редактировать: 19.01.2011: применил предложение от Криса - использование Reflection вместо ComponentModel.
Я преобразовал код, чтобы сделать его более общим. Теперь это работает для всех примитивных и пользовательских типов (воскрешение). Фрагмент кода ниже:
private object BuildParameterList(Type type)
{
object item = new object();
item = Activator.CreateInstance(type);
PropertyInfo[] propArray = type.GetProperties(BindingFlags.Public|BindingFlags.Instance);
for (int i = 0; i < propArray.Length; i++)
{
PropertyInfo pi = (PropertyInfo)propArray[i];
////Check for custom type
if (IsCustomType(pi.PropertyType))
{
object item1 = BuildParameterList(pi.PropertyType);
pi.SetValue(item, item1, null);
}
else
{
if (property.ContainsKey(pi.Name))
{
pi.SetValue(item, Convert.ChangeType(property[pi.Name], pi.PropertyType), null);
}
}
}
return item;
}
Но если одним из свойств является Color (я только что проверил с типом Color, произойдет сбой с другими типами систем, как я полагаю), то произойдет сбой в следующей строке. Не уверен, как обращаться с типами систем - Цвет или что-то подобное.
pi.SetValue(item, Convert.ChangeType(property[pi.Name], pi.PropertyType), null);