Pergunta

Procurando uma maneira de passar uma matriz associativa para um método. Eu estou olhando para reescrever um pacote de Tween Actionscript em C #, mas correndo em problemas com "associativos" matrizes / objetos. Normalmente, em Actionscript eu poderia fazer algo como:

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

E este poderia ser chamado como:

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

Eu estou procurando uma maneira de fazer o mesmo em C #. Até agora, eu recolhi minhas opções a ser:

a) a criação de uma classe ou struct para definir as teclas param e tipos possíveis e passar essa

b) passar os parâmetros como tipo genérico

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

assumindo

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

e descobrir uma maneira de usar que na função de interpolação (não tenho certeza como separar a chave = valor do dado esse objeto. Alguma idéia?)

c) criar uma Dictionary<string, object> para passar os parâmetros para a função de interpolação

Quaisquer outras idéias ou código de exemplo? Eu sou novo para C #.

Editar

Tomou-me todos os dias para descobrir isso:

"tipos anônimos não podem ser compartilhados além das fronteiras de montagem. Os garante compilador que existe no máximo um tipo anônimo para uma determinada sequência de pares nome de propriedade / tipo dentro de cada montagem. Para passar estruturas entre os conjuntos você precisará defini-los corretamente . "

Foi útil?

Solução

Editar : Este é basicamente o mecanismo que HtmlHelper extensões usar em ASP.NET MVC. Não é original com mim.


Eu favorecer uma abordagem híbrida que tem duas assinaturas diferentes. Nota: Eu não tentei isso e pode haver um conflito entre as duas assinaturas para que você pode ter que dar o segundo método um nome ligeiramente diferente para permitir que o compilador para escolher entre eles, mas eu não penso assim.

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" ))
    {
      ....
    }
}

Em seguida, você tem uma classe ParameterDictionary que usa a reflexão sobre o tipo anônimo e configura o dicionário.

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);
             }
         }
    }
}

Isto dá-lhe tanto a facilidade de uso e facilidade de consumo - o "feio" coisas reflexão é embrulhado em um único construtor para o dicionário, em vez de em seu método. E, claro, o dicionário pode ser usado repetidas vezes para fins semelhantes com o código de reflexão escrita apenas uma vez.

Outras dicas

O dicionário é uma abordagem razoável. Ele pode ter esta aparência:

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

mente que quando você passar os valores na sintaxe coleção de inicialização, você pode usar encurtado para torná-lo mais fácil, como:

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

Esta seria uma maneira muito rápida de fazer mais ou menos "a mesma coisa", como o código ActionScript, mas não é realmente grande C #. A C # forma -ish de fazê-lo seria fazer um TweenParameters struct real ou classe com propriedades de cada parâmetro possível, e, em seguida, criar um para passar para o tween (). Este é geralmente considerado mais sustentável, uma vez que todas as propriedades "disponíveis" são óbvias para um chamador sem olhar para os internos do Tween (), e porque ele pega erros em tempo de compilação que uma comparação de string não seria aviso prévio até a execução, como typoing "duração" "duratoin".

Eu sou um fã de opção (b) me - passando um tipo anônimo e analisar os valores usando a reflexão

.

Eu vi os outros a alcançar a mesma coisa usando expressões lambda. A sintaxe chamar seria:

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

E a declaração seria algo ao longo das linhas de:

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

A idéia é que você pode ter um número variável de "funções que retornam objeto". Você, então, analisar o nome do parâmetro de saída de cada Expression e chamar cada um para obter seu valor.

Eu não acho que isso é melhor do que refletir sobre um tipo anônimo, mas é uma outra abordagem para considerar.

Atualizar

Eu tenho realmente escrito sobre a idéia de passar arrays associativos como dicionários no meu blog, aqui e aqui .

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top