5

我正在使用反射器进入 Microsoft.Practices.Prism 程序集,并遇到了 DelagateCommand 的构造函数的以下定义:

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

此代码无法编译,因为: base(action, func)指向 ctor 中的前两个变量。

是否有可能复制这种行为?也许通过使用匿名方法?

预先感谢您的意见。

此方法的反射器 IL:

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

同样在查看 codeplex 的实际源代码后,方法定义如下:

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

2 回答 2

6

我认为这可能只是一个反射器错误,试图表示 lambdas 的支持委托被缓存的方式。真正的代码很可能是:

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

你有IL吗?


编辑:嗯...我无法复制。但是,还有其他两个选项:在 C++ 和 IL 中,您几乎可以做任何事情。不过,该代码看起来……很时髦。

于 2012-04-13T10:03:32.783 回答
0

恕我直言,这是反射器的失败。您为什么不查看 Prism 的源代码?

于 2012-04-13T10:04:10.960 回答