Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用表达式树创建空委托?_C#_Events_Delegates_Expression Trees - Fatal编程技术网

C# 如何使用表达式树创建空委托?

C# 如何使用表达式树创建空委托?,c#,events,delegates,expression-trees,C#,Events,Delegates,Expression Trees,使用可以创建C#2.0以来的空委托 这是例如 如何使用创建相同的行为? 我现在看到的唯一可能的选择是使用,但据我所知,这需要大量额外的工作。表达式树,根据其用途的性质,总是有一个用于主体的表达式,而不是原始设计中的语句 在C#3中,根本无法表达其主体是空语句块的表达式树。最近,表达式树库被扩展以允许语句,但C#语义分析规则没有更新以利用这一点;您仍然无法将语句lambda转换为表达式树。事实证明,使用expression.lambda()并不需要太多工作。然而,我仍然对其他可能的答案感兴趣 我确

使用可以创建C#2.0以来的空委托

这是例如

如何使用创建相同的行为?


我现在看到的唯一可能的选择是使用,但据我所知,这需要大量额外的工作。

表达式树,根据其用途的性质,总是有一个用于主体的表达式,而不是原始设计中的语句

在C#3中,根本无法表达其主体是空语句块的表达式树。最近,表达式树库被扩展以允许语句,但C#语义分析规则没有更新以利用这一点;您仍然无法将语句lambda转换为表达式树。

事实证明,使用
expression.lambda()
并不需要太多工作。然而,我仍然对其他可能的答案感兴趣

我确实需要一个我以前写过的助手方法:

/// <summary>
///   The name of the Invoke method of a Delegate.
/// </summary>
const string InvokeMethod = "Invoke";

/// <summary>
///   Get method info for a specified delegate type.
/// </summary>
/// <param name = "delegateType">The delegate type to get info for.</param>
/// <returns>The method info for the given delegate type.</returns>
public static MethodInfo MethodInfoFromDelegateType( Type delegateType )
{
    Contract.Requires(
        delegateType.IsSubclassOf( typeof( MulticastDelegate ) ),
        "Given type should be a delegate." );

    return delegateType.GetMethod( InvokeMethod );
}

稍微扩展一下Steven答案-我需要类似的功能来为-Action和Func类型创建空委托-下面是我为该任务创建的帮助程序:

    static class MethodInfoHelper<T>
    {
        static MethodInfoHelper()
        {
            VerifyTypeIsDelegate();
        }

        public static void VerifyTypeIsDelegate()
        {
            //Lets make sure this is only ever used in code for Func<> types
            if (!typeof(T).IsSubclassOf(typeof(Delegate)))
            {
                throw new InvalidOperationException(typeof(T).Name + " is not a delegate type");
            }

            if (!typeof(T).Name.StartsWith("Func") && !typeof(T).Name.StartsWith("Action"))
            {
                throw new InvalidOperationException(typeof(T).Name + " is not a Func nor an Action");
            }
        }

        private static bool HasReturnType
        {
            get { return typeof(T).Name.StartsWith("Func"); }
        }

        /// <summary>
        /// Creates an empty delegate of given type
        /// </summary>
        /// <typeparam name="T">Func or Action type to be created</typeparam>
        /// <returns>A delegate to expression doing nothing</returns>
        public static T CreateEmptyDelegate()
        {
            Type funcType = typeof(T);
            Type[] genericArgs = funcType.GenericTypeArguments;

            List<ParameterExpression> paramsExpressions = new List<ParameterExpression>();
            for (int paramIdx = 0; paramIdx < (HasReturnType ? genericArgs.Length - 1 : genericArgs.Length); paramIdx++)
            {
                Type argType = genericArgs[paramIdx];

                ParameterExpression argExpression = Expression.Parameter(argType, "arg" + paramIdx);
                paramsExpressions.Add(argExpression);
            }

            Type returnType = HasReturnType ? genericArgs.Last() : typeof(void);

            DefaultExpression emptyExpression = (DefaultExpression)typeof(DefaultExpression).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null,
                new Type[] { typeof(Type) }, null).Invoke(new[] { returnType });

            Expression<T> resultingExpression = Expression.Lambda<T>(
                emptyExpression, "EmptyDelegate", true, paramsExpressions);

            return resultingExpression.Compile();
        }
    }
静态类MethodInfoHelper
{
静态MethodInfoHelper()
{
VerifyTypeIsDelegate();
}
公共静态void VerifyTypeIsDelegate()
{
//让我们确保这只在Func类型的代码中使用
如果(!typeof(T).IsSubclassOf(typeof(Delegate)))
{
抛出新的InvalidOperationException(typeof(T).Name+“不是委托类型”);
}
如果(!typeof(T).Name.StartsWith(“Func”)和&!typeof(T).Name.StartsWith(“Action”))
{
抛出新的InvalidOperationException(typeof(T).Name+“既不是函数也不是动作”);
}
}
私有静态布尔类型
{
获取{return typeof(T).Name.StartsWith(“Func”);}
}
/// 
///创建给定类型的空委托
/// 
///要创建的Func或操作类型
///表达式的委托不做任何事情
公共静态T CreateEmptyDelegate()
{
类型funcType=typeof(T);
类型[]genericArgs=funcType.GenericTypeArguments;
列表参数pressions=新列表();
对于(int paramIdx=0;paramIdx<(HasReturnType?genericArgs.Length-1:genericArgs.Length);paramIdx++)
{
类型argType=genericArgs[paramIdx];
ParameterExpression argExpression=Expression.Parameter(argType,“arg”+paramIdx);
paramsExpressions.Add(argExpression);
}
Type returnType=HasReturnType?genericArgs.Last():typeof(void);
DefaultExpression emptyExpression=(DefaultExpression)typeof(DefaultExpression).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance,null,
新类型[]{typeof(Type)},null);
表达式resultingExpression=Expression.Lambda(
emptyExpression,“EmptyDelegate”,true,paramsExpressions);
返回resultingExpression.Compile();
}
}

我想这就是为什么只从C#4.0开始提供的原因吧?我并不是真的想把一个语句变成一个表达式树,而是相反。导致“空”委托的表达式树语句。我想我找到了,但我可能只是感到困惑@史蒂文尤里斯:啊,我误解了你问题的主旨。是的,您可以“手动”构造一个表达式树,它在逻辑上是一个空语句块。我的观点是,没有办法让C#编译器通过lambda转换为您实现这一点。
EventInfo _event;

...

MethodInfo delegateInfo
    = DelegateHelper.MethodInfoFromDelegateType( _event.EventHandlerType );
ParameterExpression[] parameters = delegateInfo
    .GetParameters()
    .Select( p => Expression.Parameter( p.ParameterType ) )
    .ToArray();
Delegate emptyDelegate = Expression.Lambda(
    _event.EventHandlerType,
    Expression.Empty(), "EmptyDelegate", true, parameters ).Compile();
    static class MethodInfoHelper<T>
    {
        static MethodInfoHelper()
        {
            VerifyTypeIsDelegate();
        }

        public static void VerifyTypeIsDelegate()
        {
            //Lets make sure this is only ever used in code for Func<> types
            if (!typeof(T).IsSubclassOf(typeof(Delegate)))
            {
                throw new InvalidOperationException(typeof(T).Name + " is not a delegate type");
            }

            if (!typeof(T).Name.StartsWith("Func") && !typeof(T).Name.StartsWith("Action"))
            {
                throw new InvalidOperationException(typeof(T).Name + " is not a Func nor an Action");
            }
        }

        private static bool HasReturnType
        {
            get { return typeof(T).Name.StartsWith("Func"); }
        }

        /// <summary>
        /// Creates an empty delegate of given type
        /// </summary>
        /// <typeparam name="T">Func or Action type to be created</typeparam>
        /// <returns>A delegate to expression doing nothing</returns>
        public static T CreateEmptyDelegate()
        {
            Type funcType = typeof(T);
            Type[] genericArgs = funcType.GenericTypeArguments;

            List<ParameterExpression> paramsExpressions = new List<ParameterExpression>();
            for (int paramIdx = 0; paramIdx < (HasReturnType ? genericArgs.Length - 1 : genericArgs.Length); paramIdx++)
            {
                Type argType = genericArgs[paramIdx];

                ParameterExpression argExpression = Expression.Parameter(argType, "arg" + paramIdx);
                paramsExpressions.Add(argExpression);
            }

            Type returnType = HasReturnType ? genericArgs.Last() : typeof(void);

            DefaultExpression emptyExpression = (DefaultExpression)typeof(DefaultExpression).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null,
                new Type[] { typeof(Type) }, null).Invoke(new[] { returnType });

            Expression<T> resultingExpression = Expression.Lambda<T>(
                emptyExpression, "EmptyDelegate", true, paramsExpressions);

            return resultingExpression.Compile();
        }
    }