ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

c# – 确定方法参数的上下文

2019-06-13 01:56:50  阅读:185  来源: 互联网

标签:c reflection parameters stack-trace


这是一个具有挑战性的问题.是否可以使用任何方法隐式确定作为参数传递给方法的属性的名称?

(这可能起初看起来像是另一个问题的副本,但是有一个微妙但重要的不同,因为我们总是使用属性,这是关键).

以下是示例场景:

    public class Foo
    {
        public string Bar { get; set; }
    }

    public void SomeStrangeMethod()
    {
        Foo foo = new Foo() { Bar = "Hello" };
        string result = FindContext(foo.Bar);  // should return "Bar"
    }

    public string FindContext(object obj)
    {
        // TODO? - figure out the property name corresponding to the passed parameter.  
        // In this example, we need to somehow figure out that the value of "obj"
        // is the value of the property foo.Bar, and return "Bar"            
    }

假设在FindContext中,传递的参数将始终是对象的属性.问题是,我们不知道是什么对象.

显然,通过传递提供缺失上下文的第二个参数可以很容易地解决问题,即……

FindContext(foo, foo.Bar);    
FindContext("Bar", foo.Bar);  

….但那不是我想要的.我希望能够传递单个参数并确定值所代表的属性名称.

我知道,当传递参数时,FindContext的方法上下文不包含足够的信息来确定这一点.但是,使用堆栈跟踪和IL的一些手法,也许我们仍然可以做到这一点.我认为这必须是可能的原因是:

>要求传递给FindContext的参数必须始终是另一个对象的属性,并且我们知道可以使用反射获取所述属性名称.
>使用StackTrace,我们可以获得调用上下文.
>在调用上下文之外,我们应该能够以某种方式找到正在使用的符号.
>从该符号,我们应该能够检索属性名称和/或调用对象的类型,通过(1)我们应该能够转换为调用对象的属性.

有人知道怎么做这个吗?注意:这个问题很难,但我不相信这是不可能的.除非有人能证明为什么不可能,否则我不会接受任何“不可能”的答案.

解决方法:

如果你传递一个lambda表达式,你可以

public class Foo
{
    public string Bar { get; set; }
}

public void SomeStrangeMethod()
{
    Foo foo = new Foo() { Bar = "Hello" };
    string result = GetName(()=>foo.Bar);  // should return "Bar"
    Debug.WriteLine(result); // "Bar"
}


public static string GetName<T>(Expression<Func<T>> expression)
{
    return ExtractPropertyName(expression);
}

/// <summary>
/// Extracts the name of a property from a suitable LambdaExpression.
/// </summary>
/// <param name="propertyExpression">The property expression.</param>
/// <returns></returns>
public static string ExtractPropertyName(LambdaExpression propertyExpression)
{
    if (propertyExpression == null)
    {
        throw new ArgumentNullException("propertyExpression");
    }

    var memberExpression = propertyExpression.Body as MemberExpression;
    if (memberExpression == null)
    {
        throw new ArgumentException(@"Not a member expression", "propertyExpression");
    }

    var property = memberExpression.Member as PropertyInfo;
    if (property == null)
    {
        throw new ArgumentException(@"Not a property", "propertyExpression");
    }

    var getMethod = property.GetGetMethod(true);
    if (getMethod.IsStatic)
    {
        throw new ArgumentException(@"Can't be static", "propertyExpression");
    }

    return memberExpression.Member.Name;
}

标签:c,reflection,parameters,stack-trace
来源: https://codeday.me/bug/20190613/1229738.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有