我想有一个方法为Action<sender,args>
创建一个包装器,所以当我想通过这个包装器调用这个动作时,我可以检查调用者是否为null。
以下是我创建包装器的方法:
public void Subscribe<TEventArgs>(Expression<Func<Action<object,TEventArgs>> expression)
{
wrapper=new EventHandlerWrapper{Expression=expression};
Subscribe<TEventArgs>(wrapper.GetHandler());
}
因此我可以这样称呼这个方法:
var handler=new MyHandler();
Subscribe(()=>handler.EventHandler);
然后我希望能够使用表达式
获取调用者实例(上面代码中的处理程序)我传递的表达式是UnaryExpresison
。我可以找到很多解决方案来说明我们如何从MemberExpression
获取调用者但是在这里我无法抓住任何MemberExpression
1}}。我有一个UnaryExpression
,其Operand
是MethodCallExpression
,作为回报,Object
是ConstantExpression
,我被困在这里。
如何获取调用者实例?
更新
顺便说一句,EventHandler
不是动作本身就是这样的方法:
public class MyHandler
{
public void EventHandler(object sender,EventArgs e)
{
.....
}
}
以下是Wrapper.GetHandler()
的签名:
public Action<object, TArgs> GetHandleAction()
{
return (sender, args) =>
{
if (Handler != null)
{
HandlerExpression.Compile()();
}
};
}
Handler
是我想使用给定表达式填充它的调用者实例。
让问题清晰:我想从Expression<Func<Action<object,object>>
获取来电者实例。
答案 0 :(得分:1)
你可以这样:
var member = (((expression.Body as UnaryExpression).Operand as MethodCallExpression).Arguments[1] as MemberExpression);
var constant = (member.Expression as ConstantExpression);
var f = member.Member;
if ((f is FieldInfo))
{
// here is your caller instance, do your checks.
var callerInstance = ((FieldInfo)f).GetValue(constant.Value);
}
(基于:How to get Property Value from MemberExpression without .Compile()?)
答案 1 :(得分:1)
在您给出的这个非常具体的示例中,您可以使用以下命令从表达式中提取handler
:
private static void Subscribe<TEventArgs>(Expression<Func<Action<object, TEventArgs>>> expression)
{
var accessor = ((MethodCallExpression)((UnaryExpression)expression.Body).Operand).Arguments[1];
var handlerFunc = Expression.Lambda<Func<object>>(accessor).Compile();
var handler = handlerFunc();
// handler now contains the instance you're interested in
}
如果您可以确保拨打Subscribe
的电话始终是您提供的表格,那么这应该有效,但它非常脆弱。
还值得存储handlerFunc
而不是handler
,因为对Subscribe<EventArgs>(() => handler.EventHandler)
的调用会创建一个捕获handler
变量的闭包,不它的价值。因此,如果您要将handler
设置为null
,或者在调用Subscribe
后将其设置为其他值,则会调用新值EventHandler
,而不是Subscribe
电话时的价值。