如何使用表达式树创建一个空委托?

使用匿名方法,您可以创建自C#2.0以来的空委托。

public event EventHandler SomeEvent = delegate {}; public event Action OtherEvent = delegate {}; 

这对于防止在调用事件时必须进行空检查非常有用 。

如何使用表达式树创建相同的行为?

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

表达式树,就其目的而言,总是有一个表达式,而不是原始设计中的声明。

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

事实certificate使用Expression.Lambda()并没有那么多工作。 但是,我仍然对其他可能的答案感兴趣。

我确实需要一个我之前写过的辅助方法:

 ///  /// The name of the Invoke method of a Delegate. ///  const string InvokeMethod = "Invoke"; ///  /// Get method info for a specified delegate type. ///  /// The delegate type to get info for. /// The method info for the given delegate type. public static MethodInfo MethodInfoFromDelegateType( Type delegateType ) { Contract.Requires( delegateType.IsSubclassOf( typeof( MulticastDelegate ) ), "Given type should be a delegate." ); return delegateType.GetMethod( InvokeMethod ); } 

当你有EventInfo你可以为它创建一个空的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(); 

扩展Steven的答案 – 我需要类似的function来为两者创建一个空委托 – Action和Func类型 – 以下是我为该任务创建的帮助程序:

  static class MethodInfoHelper { 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"); } } ///  /// Creates an empty delegate of given type ///  /// Func or Action type to be created /// A delegate to expression doing nothing public static T CreateEmptyDelegate() { Type funcType = typeof(T); Type[] genericArgs = funcType.GenericTypeArguments; List paramsExpressions = new List(); 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 resultingExpression = Expression.Lambda( emptyExpression, "EmptyDelegate", true, paramsExpressions); return resultingExpression.Compile(); } }