Создать список параметров с пользовательскими типами во время выполнения (используя C #) - PullRequest
0 голосов
/ 18 января 2011

В рамках моего проекта я пытаюсь создать веб-интерфейс, в котором пользователь выбирает метод и передает значения. Моя программа должна иметь возможность динамически вызывать метод и создавать список параметров во время выполнения, чтобы передать его методу.

Я создал разделенный запятыми список (строку) пар ключ и значение. Эта пара ключ / значение - не что иное, как имя параметра и значение моего метода (имя метода хранится в переменной). Пример: 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);

1 Ответ

0 голосов
/ 18 января 2011

Не можете найти, какие типы ожидаются методом, проверяя его ParameterInfo s:

endpoint.Contract.ContractType.GetMethod(methodName).GetParameters();

и затем создание пользовательских типов с помощью:

Activator.CreateInstance(parameterType);
...