Domanda

ricerca di un modo per passare un array associativo a un metodo. Sto cercando di riscrivere un pacchetto tween Actionscript in C #, ma incorrere in guai con "associative" matrici / oggetti. Normalmente in Actionscript potrei fare qualcosa di simile:

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

E questo potrebbe essere chiamato come:

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

Sto cercando un modo per fare la stessa cosa in C #. Finora, ho raccolto le mie opzioni per essere:

a) creare una classe o struttura per definire i tasti param e tipi possibili e pass che

b) passare i parametri come tipo generico

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

assumendo

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

e capire un modo per utilizzare che nella funzione tween (non sono sicuro di come separare la chiave = valore del dato quell'oggetto. Tutte le idee?)

c) creare un Dictionary<string, object> passare i parametri di interpolazione nella funzione

Tutte le altre idee o codice di esempio? Sono nuovo di C #.

Modifica

Mi ha portato tutto il giorno per capire questo:

"tipi anonimi non possono essere condivisi attraverso i confini di montaggio. Il compilatore assicura che ci sia al massimo un tipo anonimo per una data sequenza di coppie nome della proprietà / tipo all'interno di ogni gruppo. Per passare strutture tra assemblee è necessario definirli correttamente ".

È stato utile?

Soluzione

Modifica : Questo è fondamentalmente il meccanismo che HtmlHelper estensioni usano in ASP.NET MVC. Non è originale con me.


Mi piacerebbe favorire un approccio ibrido che ha due firme diverse. Nota: Non ho provato questo e non ci può essere un conflitto tra le due firme in modo da avere per dare il secondo metodo un nome leggermente diverso per permettere al compilatore di scegliere tra di loro, ma io non la penso così

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

Poi si dispone di una classe ParameterDictionary che utilizza la riflessione sul tipo anonimo e imposta il dizionario.

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

In questo modo si dà sia la facilità d'uso e la facilità di consumo - la roba di riflessione "brutto" è avvolto nel singolo costruttore per la dizionario piuttosto che nel metodo. E, naturalmente, il dizionario può essere utilizzato più e più volte per scopi simili con il codice di riflessione solo scritto una volta.

Altri suggerimenti

Il Dizionario è un approccio ragionevole. Potrebbe assomigliare a questo:

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

Ricordate che quando si passa i valori nella sintassi raccolta di inizializzazione, è possibile utilizzare accorciato per rendere più facile, come:

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

Questo sarebbe un bel modo rapido per fare più o meno "la stessa cosa", come il codice ActionScript, ma non è davvero grande C #. Il modo in cui -ish C # per farlo sarebbe quello di fare un vero e proprio TweenParameters struct o classe con le proprietà per ciascun parametro è possibile, e quindi creare uno a passare nelle Tween (). Questo è generalmente considerato più gestibile, dal momento che tutte le proprietà "disponibili" sono evidenti ad un chiamante senza guardare negli interni di Tween (), sia perché cattura errori in fase di compilazione che un confronto di stringhe non se ne accorgesse fino al runtime, come typoing "durata" "duratoin".

sono un fan di opzione (b) me -. Passa un tipo anonimo e l'analisi i valori utilizzando la riflessione

Ho visto gli altri a raggiungere la stessa cosa usando le espressioni lambda. La sintassi chiamando potrebbe essere:

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

E la dichiarazione sarebbe qualcosa sulla falsariga di:

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

L'idea è che si può prendere un numero variabile di "funzioni che restituiscono oggetto". È quindi analizzare il nome del parametro da ogni Espressione , e richiamare ognuno per ottenere il suo valore.

Non credo che questo è meglio di riflettere su un tipo anonimo, ma è un altro approccio da considerare.

Aggiorna

Ho effettivamente scritto circa l'idea di passare array associativi come dizionari sul mio blog, qui e qui .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top