C# 如何从UnaryExpression获取调用方实例?
我想有一个方法为C# 如何从UnaryExpression获取调用方实例?,c#,expression,C#,Expression,我想有一个方法为操作创建一个包装,这样当我想通过这个包装调用这个操作时,我可以检查调用方是否为null 下面是我创建包装器的方式: public void Subscribe<TEventArgs>(Expression<Func<Action<object,TEventArgs>> expression) { wrapper=new EventHandlerWrapper{Expression=expression}; Subscrib
操作创建一个包装,这样当我想通过这个包装调用这个操作时,我可以检查调用方是否为null
下面是我创建包装器的方式:
public void Subscribe<TEventArgs>(Expression<Func<Action<object,TEventArgs>> expression)
{
wrapper=new EventHandlerWrapper{Expression=expression};
Subscribe<TEventArgs>(wrapper.GetHandler());
}
然后,我希望能够使用表达式获取调用方实例(上述代码中的处理程序)
我正在传递的表达式是一个UnaryExpression
。我可以找到很多解决方案来说明如何从MemberExpression
获取调用方,但在这里我无法获取任何MemberExpression
。我有一个UnaryExpression
的操作数是MethodCallExpression
,其中返回它的对象
是一个常量表达式
,我被卡在这里了。
如何获取调用方实例
更新:
顺便说一句,EventHandler
本身不是一个动作,而是一个如下的方法:
public class MyHandler
{
public void EventHandler(object sender,EventArgs e)
{
.....
}
}
以下是Wrapper.GetHandler()
的签名:
公共行动GetHandleAction()
{
返回(发送方,参数)=>
{
if(处理程序!=null)
{
HandlerExpression.Compile();
}
};
}
Handler
是我希望使用给定表达式填充的调用方实例
为了澄清我的问题:我想从表达式中获取调用者实例您可以这样得到它:
var handler=new MyHandler();
Subscribe(()=>handler.EventHandler);
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);
}
(基于:)在您给出的这个非常具体的示例中,您可以使用以下命令从表达式中提取处理程序
:
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
}
private static void Subscribe(表达式)
{
变量访问器=((MethodCallExpression)((UnaryExpression)expression.Body.Operator).Arguments[1];
var handlerFunc=Expression.Lambda(accessor.Compile();
var handler=handlerFunc();
//处理程序现在包含您感兴趣的实例
}
如果您可以确保对Subscribe
的调用总是以您给出的形式进行,那么这应该是可行的,但它非常脆弱
同样值得存储handlerFunc
而不是handler
,因为调用Subscribe(()=>handler.EventHandler)
会创建一个闭包,该闭包捕获的是handler
变量,而不是它的值。同样地,如果要将处理程序设置为null
,或者在调用Subscribe
后设置为不同的值,则将调用的将是新值的事件处理程序
,而不是Subscribe
调用时的值。对于全图,我们都忽略了GetHandler()这一行中的Subscribe定义:“Subscribe(wrapper.GetHandler());@qbik我将把它们添加到我的问题中。如果你在问题中加入实际的、可编译的代码,那将非常有帮助。事实上,代码中有太多问题,以至于你甚至不清楚你在尝试做什么。例如,Subscribe
似乎是无限递归的,除非你没有给出另一个重载,并且是包装器
一个字段,或者您是否忘记将var
放在它前面。另外,如果您已给出Wrapper.GetHandler()
的签名,则该方法实际上称为GetHandleAction()
。请检查您的问题,并确保所包含的代码能够真正编译并尽可能接近您所使用的内容。@Iridium我编辑了我的问题,并用一句简单的话进行了提问。
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
}