2012-04-13 28 views
5

stavo colpendo in Microsoft.Practices.Prism assembly utilizzando riflettore e sono imbattuto nel seguente definizione per il costruttore di DelagateCommand:C# costruttore parola chiave base

public DelegateCommand(Action executeMethod, Func<bool> canExecuteMethod) 
    : base(action, func) 
{ 
    Action<object> action = null; 
    Func<object, bool> func = null; 
    if (action == null) 
    { 
     action = o => executeMethod(); 
    } 
    if (func == null) 
    { 
     func = o => canExecuteMethod(); 
    } 
    if ((executeMethod == null) || (canExecuteMethod == null)) 
    { 
     throw new ArgumentNullException(
      "executeMethod", 
      Resources.DelegateCommandDelegatesCannotBeNull); 
    } 
} 

Questo codice non compila in quanto : base(action, func) punti per i primi due variabili nel ctor.

È possibile replicare questo tipo di comportamento? forse con l'uso di metodi anon?

Grazie in anticipo per il vostro contributo.

Riflettore IL per questo metodo:

.method public hidebysig specialname rtspecialname instance void .ctor(class [mscorlib]System.Action executeMethod, class [mscorlib]System.Func`1<bool> canExecuteMethod) cil managed 
{ 
    .maxstack 5 
    .locals init (
     [0] class [mscorlib]System.Action`1<object> action, 
     [1] class [mscorlib]System.Func`2<object, bool> func, 
     [2] class Microsoft.Practices.Prism.Commands.DelegateCommand/<>c__DisplayClass6 class2) 
    L_0000: ldnull 
    L_0001: stloc.0 
    L_0002: ldnull 
    L_0003: stloc.1 
    L_0004: newobj instance void Microsoft.Practices.Prism.Commands.DelegateCommand/<>c__DisplayClass6::.ctor() 
    L_0009: stloc.2 
    L_000a: ldloc.2 
    L_000b: ldarg.1 
    L_000c: stfld class [mscorlib]System.Action Microsoft.Practices.Prism.Commands.DelegateCommand/<>c__DisplayClass6::executeMethod 
    L_0011: ldloc.2 
    L_0012: ldarg.2 
    L_0013: stfld class [mscorlib]System.Func`1<bool> Microsoft.Practices.Prism.Commands.DelegateCommand/<>c__DisplayClass6::canExecuteMethod 
    L_0018: ldarg.0 
    L_0019: ldloc.0 
    L_001a: brtrue.s L_0029 
    L_001c: ldloc.2 
    L_001d: ldftn instance void Microsoft.Practices.Prism.Commands.DelegateCommand/<>c__DisplayClass6::<.ctor>b__2(object) 
    L_0023: newobj instance void [mscorlib]System.Action`1<object>::.ctor(object, native int) 
    L_0028: stloc.0 
    L_0029: ldloc.0 
    L_002a: ldloc.1 
    L_002b: brtrue.s L_003a 
    L_002d: ldloc.2 
    L_002e: ldftn instance bool Microsoft.Practices.Prism.Commands.DelegateCommand/<>c__DisplayClass6::<.ctor>b__3(object) 
    L_0034: newobj instance void [mscorlib]System.Func`2<object, bool>::.ctor(object, native int) 
    L_0039: stloc.1 
    L_003a: ldloc.1 
    L_003b: call instance void Microsoft.Practices.Prism.Commands.DelegateCommandBase::.ctor(class [mscorlib]System.Action`1<object>, class [mscorlib]System.Func`2<object, bool>) 
    L_0040: ldloc.2 
    L_0041: ldfld class [mscorlib]System.Action Microsoft.Practices.Prism.Commands.DelegateCommand/<>c__DisplayClass6::executeMethod 
    L_0046: brfalse.s L_0050 
    L_0048: ldloc.2 
    L_0049: ldfld class [mscorlib]System.Func`1<bool> Microsoft.Practices.Prism.Commands.DelegateCommand/<>c__DisplayClass6::canExecuteMethod 
    L_004e: brtrue.s L_0060 
    L_0050: ldstr "executeMethod" 
    L_0055: call string Microsoft.Practices.Prism.Properties.Resources::get_DelegateCommandDelegatesCannotBeNull() 
    L_005a: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string, string) 
    L_005f: throw 
    L_0060: ret 
} 

Anche dopo esaminando la reale source code al CodePlex la definizione del metodo è il seguente:

public DelegateCommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod) 
      : base((o) => executeMethod((T)o), (o) => canExecuteMethod((T)o)) 
     { 
      if (executeMethod == null || canExecuteMethod == null) 
       throw new ArgumentNullException("executeMethod", Resources.DelegateCommandDelegatesCannotBeNull); 

#if !WINDOWS_PHONE 
      Type genericType = typeof(T); 

      // DelegateCommand allows object or Nullable<>. 
      // note: Nullable<> is a struct so we cannot use a class constraint. 
      if (genericType.IsValueType) 
      { 
       if ((!genericType.IsGenericType) || (!typeof(Nullable<>).IsAssignableFrom(genericType.GetGenericTypeDefinition()))) 
       { 
        throw new InvalidCastException(Resources.DelegateCommandInvalidGenericPayloadType); 
       } 
      } 
#endif 
     } 

risposta

6

penso che questo sia probabilmente solo un riflettore bug, cercando di rappresentare il modo in cui il delegato di supporto per lambda viene memorizzato nella cache. Il codice reale è più probabile:

: base(o => executeMethod(), o => canExecuteMethod()) 

Avete a disposizione l'IL?


Modifica: Hmmm ... Non riesco a ripeterlo. Ci sono altre due opzioni, però: sia in C++ che in IL puoi fare praticamente qualsiasi cosa. Quel codice sembra ... funky, comunque.

+1

Sì, questa è la chiamata base reale in base alla fonte (ad eccezione della sorgente ha parentesi ridondanti: P) ... in PrismLibrary \ Desktop \ Prism \ Comandi \ DelegateCommand.cs – BoltClock

+0

@ BoltClock'saUnicorn in quel caso, il mio riflettore deve essere diverso dagli OP - ottengo la giusta uscita ... a meno che non sia impertinente e scrutino il mio .pdb –

+0

È chiaramente un errore di riflettore ma questo codice sembra davvero funzionale! –

0

IMHO, è il fallimento di Reflector. Perché non guardi nel codice sorgente di Prism?