在setter中获取属性名称

Posted

技术标签:

【中文标题】在setter中获取属性名称【英文标题】:Get property name inside setter 【发布时间】:2010-11-05 21:10:55 【问题描述】:

我想在 ASP.Net 应用程序的回发之间保留一个属性。目前正在这样做:

public int MyIndex

    get
    
        return (int)Session[ToString() + "MyIndex"];
    

但更喜欢类似的东西:

public int MyIndex

    get
    
        return (int)Session[ToString() + #code_that_returns_property_name#];
    

Setter 省略,但它只是使用相同的字符串将值推送到 Session 中。 有什么方法可以使用反射,或者其他更好的解决方案?

【问题讨论】:

看起来我们终于有一些syntactic candy coming 来为我们解决这个问题:“通常你需要提供一个字符串来命名一些程序元素:当抛出 ArgumentNullException 时,你想命名有罪的参数;当引发要命名更改的属性等的 PropertyChanged 事件。” if (x == null) throw new ArgumentNullException(nameof(x)); 【参考方案1】:
public static int Dummy 
    get 
        var propertyName = MethodBase.GetCurrentMethod().Name.Substring(4);
        Console.WriteLine(propertyName);
        return 0;
    

【讨论】:

不,它有效。不确定该异常来自哪里。现在工作正常。正是我需要的。 看在上帝的份上,不!结果比它所取代的要长五倍,晦涩难懂 100 倍!除非你要不断地改变你对如何称呼该属性的想法,否则这是一个荒谬的想法。 (...恕我直言) 除了其他 cmets 之外,这种方法会慢数百(数千?)倍,反射并不便宜。这可能不是 OP 关心的问题,但任何考虑此类事情的人都需要注意。 (在我的机器上做一个简单的测试,反射版本 10000000 次调用耗时 71 秒,硬编码版本耗时 0.8 秒) 查看我使用 CallerMemberName 处理速度问题的答案。【参考方案2】:

使用 CallerMemberName 速度要快得多,并且可以轻松复制和粘贴其他属性。

private static object GetSessionValue([CallerMemberName]string propertyName = "") 

    return Session[propertyName];


private static void SetSessionValue(object value, [CallerMemberName]string propertyName = "") 

    Session[propertyName] = value;


public int MyIndex

    get  return (int)GetSessionValue(); 
    set  SetSessionValue(value); 

【讨论】:

这个答案是最好的方法,因为它在编译时而不是在运行时工作。 太好了,我在framework 4.0 中寻找这个已经很久了。谢谢,我的代码 4.5+ 终于变得更容易维护了。【参考方案3】:

不,没有简单的方法可以做你想做的事。我认为您已经编写的代码好多了

编辑: 这个答案已经收到不少反对票,我明白为什么。虽然可以做 OP 想要做的事情,但也许我们都应该停下来思考这样做是否可取。套用Dr. Ian Malcom的不朽之言,仅仅因为你能做某事并不意味着你应该。

【讨论】:

为什么投反对票?这是最明智的答案... :) 来自我的 +1。 我也+1,这是一个疯狂的想法。如果你发现你必须做很多事情,并且名称不断变化,因此管理它成为一种负担,那么使用 .tt 文件来代码生成属性声明或类似的东西。 +1 和接受的答案。我可以看到为什么 OP 想要这样做,以及缓解因素:如果所讨论的属性只是 40 个中的一个,那么对于与 40 个硬编码属性名称分离的单个实现有一些话要说。当然,缓解因素是,如果 OP 知道这些属性只设置一次或少量次,则此级别的性能没有实际意义。避免过早优化。 我可以否决,因为“没有一种简单的方法可以做你想做的事”。这是误导。【参考方案4】:

您可以使用 MethodInfo.GetCurrentMethod().Name 返回当前方法的名称:

public int MyIndex

    get
    
        return (int)Session[ToString() + MethodInfo.GetCurrentMethod().Name];
    

由于属性是作为底层方法实现的,因此将返回类似“get_MyIndex”的名称。如果你不想要“get_”部分,你可以把几个字符子串出来:

public int MyIndex

    get
    
        return (int)Session[ToString() + MethodInfo.GetCurrentMethod().Name.Substring(4)];
    

【讨论】:

【参考方案5】:

您可以使用表达式树来获取成员名称。这有点笨拙,但它有效。这是代码。

private string GetPropertyName<TValue>(Expression<Func<BindingSourceType, TValue>> propertySelector)

    var memberExpression = propertySelector.Body as MemberExpression;
    if (memberExpression != null)
    
        return memberExpression.Member.Name;
    
    else
    
       return string.empty;    
    

使用该代码,您可以执行以下操作

return (int)Session[ToString() + GetPropertyName(MyIndex)];

Romain 在以下线程的回答中无情地窃取了代码

Get class property name

【讨论】:

如果您从另一个线程阅读原始答案,它会说 BindingSourceType 是包含该属性的类名。您需要使用属性 MyIndex 所属的类的名称。【参考方案6】:

您应该使用控件的ViewState 属性:

public int MyIndex 
    get  
        object index = ViewState["MyIndex"];
        return (null == index) ? -1 : (int)index;
    
    set 
        ViewState["MyIndex"] = value;
    

【讨论】:

以上是关于在setter中获取属性名称的主要内容,如果未能解决你的问题,请参考以下文章

如何在python中获取属性的setter方法的属性

Struts 获取表单数据总结

JS中的getter和setter

C++ getter 和 setter 不传递变量

Python如何获取用property.setter包装的方法的__qualname__

如何根据java中的输入数据顺序/名称动态调用不同的setter方法?