2012-04-13 23 views
5

que estaba hurgando en el conjunto de Microsoft.Practices.Prism usando el reflector y me encontré con la siguiente definición para el constructor de DelagateCommand:C# Constructor de palabras clave de 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); 
    } 
} 

Este código no compila desde : base(action, func) puntos a los dos primeros variables en el ctor.

¿Es posible reproducir este tipo de comportamiento? tal vez por el uso de métodos anon?

Gracias de antemano por su contribución.

Reflector IL para este método:

.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 
} 

también después de mirar en el actual source code en CodePlex la definición del método es el siguiente:

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 
     } 

Respuesta

6

creo que esto es probablemente simplemente un reflector error, tratando de representar la forma en que el delegado de respaldo para lambdas se almacena en caché. El código real es más probable:

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

¿Tiene el IL a mano?


Edit: Hmmm ... No puedo reproducir eso. Sin embargo, hay otras dos opciones: tanto en C++ como en IL, puedes hacer casi cualquier cosa. Ese código parece ... funky, sin embargo.

+1

Sí, esa es la llamada base real según la fuente (excepto que la fuente tiene paréntesis redundantes: P) ... en PrismLibrary \ Desktop \ Prism \ Commands \ DelegateCommand.cs – BoltClock

+0

@ BoltClock'saUnicorn en ese caso, mi reflector debe ser diferente a los OPs - obtengo el resultado correcto ... a menos que sea descarado y pruebe mi .pdb –

+0

¡Es claramente un error reflector pero este código se ve realmente raro! –

0

En mi humilde opinión, es un error del reflector. ¿Por qué no miras el código fuente de Prism?