Краткий метод передачи ассоциативных массивов в метод - PullRequest
1 голос
/ 10 февраля 2009

Ищем способ передачи ассоциативного массива в метод. Я пытаюсь переписать анимационный пакет Actionscript в C #, но у меня возникают проблемы с «ассоциативными» массивами / объектами. Обычно в Actionscript я могу сделать что-то вроде:

public function tween(obj:DisplayObject, params:Object = null):void {
    if (params.ease != null) {
        //do something
    }
    //...
}

И это можно назвать так:

tween(this, {ease:'out', duration:15});

Я ищу способ сделать то же самое в C #. Пока я собрал свои варианты:

a) создание класса или структуры для определения возможных ключей и типов параметров и передачи этого

b) передать параметры как универсальный тип

tween(frameworkElement, new {ease = 'out', duration = 15});

при условии

public static void tween(FrameworkElement target, object parameters);

и выясните, как использовать это в функции анимации (я не уверен, как отделить ключ = значение от данного объекта. Есть идеи?)

в) создать Dictionary<string, object> для передачи параметров в функцию анимации

Есть еще идеи или пример кода? Я новичок в C #.

Редактировать

У меня ушел целый день, чтобы понять это:

"Анонимные типы не могут совместно использоваться через границы сборок. Компилятор обеспечивает наличие не более одного анонимного типа для данной последовательности пар имя / тип свойства в каждой сборке. Чтобы передавать структуры между сборками, вам необходимо правильно определить их . "

Ответы [ 3 ]

1 голос
/ 10 февраля 2009

Словарь - разумный подход. Это может выглядеть так:

public static void tween(FrameworkElement target, IDictionary<string, object> parameters)
{
    if (parameters.ContainsKey("ease")) {
        //do something
    }
}

Помните, что когда вы передаете значения, вы можете использовать сокращенный синтаксис инициализации коллекции, чтобы упростить его, например:

tween(something, new Dictionary<string, object> { { "ease", "out" }, { duration, 15 } });

Это был бы довольно быстрый способ сделать примерно "то же самое", что и код ActionScript, но это не очень хороший C #. C # -ish способ сделать это состоял бы в том, чтобы создать реальную структуру или класс TweenParameters со свойствами для каждого возможного параметра, а затем создать его для передачи в tween (). Как правило, это считается более понятным, так как все «доступные» свойства очевидны для вызывающей стороны без изучения внутренних функций tween () и потому, что во время компиляции он обнаруживает ошибки, которые при сравнении строк не замечает до времени выполнения, например опечатка "продолжительность" "дуратоин".

1 голос
/ 10 февраля 2009

EDIT : Это в основном механизм, используемый расширениями HtmlHelper в ASP.NET MVC. Это не оригинально со мной.


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

public static void tween( FrameworkElement target, object parameters )
{
    return tween( target, new ParameterDictionary( parameters ) );
}

public static void tween( FrameworkElement target,
                          ParameterDictionary values )
{
    if (values.ContainsKey( "ease" ))
    {
      ....
    }
}

Затем у вас есть класс ParameterDictionary, который использует отражение в анонимном типе и устанавливает словарь.

public class ParameterDictionary : Dictionary<string,object>
{
    public ParameterDictionary( object parameters )
    {
         if (parameters != null)
         {
             foreach (PropertyInfo info in parameters.GetType()
                                                     .GetProperties())
             {
                 object value = info.GetValue(parameters,null);
                 this.Add(info.Name,value);
             }
         }
    }
}

Это дает вам как простоту использования, так и удобство использования - «уродливые» средства отражения заключены в одном конструкторе для словаря, а не в вашем методе. И, разумеется, словарь можно использовать снова и снова для аналогичных целей с кодом отражения, написанным только один раз.

1 голос
/ 10 февраля 2009

Я болею за вариант (б) сам - передавая анонимный тип и анализируя значения с помощью отражения.

Я видел, как другие достигли того же, используя лямбда-выражения. Синтаксис вызова будет:

tween(frameworkElement, ease => "out", duration => 15);

И объявление будет выглядеть примерно так:

public static void tween(FrameworkElement target, params Expression<Func<object>>[] parameters) { ... }

Идея состоит в том, что вы можете взять переменное число «функций, которые возвращают объект». Затем вы анализируете имя параметра из каждого выражения и вызываете каждый из них, чтобы получить его значение.

Не думаю, что это лучше, чем размышлять над анонимным типом, но это еще один подход к рассмотрению.

Обновление

На самом деле я написал об идее передачи ассоциативных массивов в качестве словарей в своем блоге здесь и здесь .

...