如何使用表达式树创建一个空委托?
使用匿名方法,您可以创建自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(); } }