Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/286.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.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# 如何从UnaryExpression获取调用方实例?_C#_Expression - Fatal编程技术网

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
}