在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中获取属性名称的主要内容,如果未能解决你的问题,请参考以下文章