以stringforms获取财产的名称

(请参阅下面我使用我接受的答案创build的解决scheme)

我正试图提高涉及reflection的一些代码的可维护性。 该应用程序有一个.NET Remoting接口公开(除其他外)一个名为Execute的方法,以访问未包含在其已发布的远程接口中的应用程序部分。

下面是应用程序如何指定属性(在这个例子中是一个静态的属性),这些属性可以通过执行来访问:

RemoteMgr.ExposeProperty("SomeSecret", typeof(SomeClass), "SomeProperty"); 

所以远程用户可以调用:

 string response = remoteObject.Execute("SomeSecret"); 

并且应用程序将使用reflection来查找SomeClass.SomeProperty并以stringforms返回其值。

不幸的是,如果有人重命名SomeProperty并忘记更改ExposeProperty()的第三个参数,它会打破这个机制。

我需要相当于:

 SomeClass.SomeProperty.GetTheNameOfThisPropertyAsAString() 

作为ExposeProperty中的第三个参数使用,所以重构工具将负责重命名。

有没有办法做到这一点? 提前致谢。

好的,这是我最终创build的(根据我select的答案和他所引用的问题):

 // <summary> // Get the name of a static or instance property from a property access lambda. // </summary> // <typeparam name="T">Type of the property</typeparam> // <param name="propertyLambda">lambda expression of the form: '() => Class.Property' or '() => object.Property'</param> // <returns>The name of the property</returns> public string GetPropertyName<T>(Expression<Func<T>> propertyLambda) { var me = propertyLambda.Body as MemberExpression; if (me == null) { throw new ArgumentException("You must pass a lambda of the form: '() => Class.Property' or '() => object.Property'"); } return me.Member.Name; } 

用法:

 // Static Property string name = GetPropertyName(() => SomeClass.SomeProperty); // Instance Property string name = GetPropertyName(() => someObject.SomeProperty); 

现在有了这个很酷的function,现在是时候简化ExposeProperty方法。 抛光门把手是危险的工作…

感谢大家。

从这里使用GetMemberInfo: 从lambdaexpression式检索属性名称,你可以做这样的事情:

RemoteMgr.ExposeProperty(() => SomeClass.SomeProperty)

 public class SomeClass { public static string SomeProperty { get { return "Foo"; } } } public class RemoteMgr { public static void ExposeProperty<T>(Expression<Func<T>> property) { var expression = GetMemberInfo(property); string path = string.Concat(expression.Member.DeclaringType.FullName, ".", expression.Member.Name); // Do ExposeProperty work here... } } public class Program { public static void Main() { RemoteMgr.ExposeProperty("SomeSecret", () => SomeClass.SomeProperty); } } 

使用C#6.0,现在这是一个非问题,你可以这样做:

 nameof(SomeProperty) 

这个expression式在编译时parsing为"SomeProperty"

有一个众所周知的黑客从lambdaexpression式中提取它(这是从他的MVVM基础上的Josh Smith的PropertyObserver类):

  private static string GetPropertyName<TPropertySource> (Expression<Func<TPropertySource, object>> expression) { var lambda = expression as LambdaExpression; MemberExpression memberExpression; if (lambda.Body is UnaryExpression) { var unaryExpression = lambda.Body as UnaryExpression; memberExpression = unaryExpression.Operand as MemberExpression; } else { memberExpression = lambda.Body as MemberExpression; } Debug.Assert(memberExpression != null, "Please provide a lambda expression like 'n => n.PropertyName'"); if (memberExpression != null) { var propertyInfo = memberExpression.Member as PropertyInfo; return propertyInfo.Name; } return null; } 

对不起,这是缺less一些上下文。 这是TPropertySource是包含属性的类的较大类的一部分。 你可以使TPropertySource中的函数通用来从类中提取它。 我build议看看MVVM基金会的完整代码。

好的,这是我最终创build的(根据我select的答案和他所引用的问题):

 // <summary> // Get the name of a static or instance property from a property access lambda. // </summary> // <typeparam name="T">Type of the property</typeparam> // <param name="propertyLambda">lambda expression of the form: '() => Class.Property' or '() => object.Property'</param> // <returns>The name of the property</returns> public string GetPropertyName<T>(Expression<Func<T>> propertyLambda) { var me = propertyLambda.Body as MemberExpression; if (me == null) { throw new ArgumentException("You must pass a lambda of the form: '() => Class.Property' or '() => object.Property'"); } return me.Member.Name; } 

用法:

 // Static Property string name = GetPropertyName(() => SomeClass.SomeProperty); // Instance Property string name = GetPropertyName(() => someObject.SomeProperty); 

如果我理解正确, PropertyInfo类应该可以帮助您实现这一目标。

  1. Type.GetProperties()方法

     PropertyInfo[] propInfos = typeof(ReflectedType).GetProperties(); propInfos.ToList().ForEach(p => Console.WriteLine(string.Format("Property name: {0}", p.Name)); 

这是你需要的吗?

您可以使用reflection来获取属性的实际名称。

http://www.csharp-examples.net/reflection-property-names/

如果你需要一种方法来给一个属性分配一个“string名称”,为什么不写一个属性,你可以通过reflection来获取string名?

 [StringName("MyStringName")] private string MyProperty { get { ... } } 

我修改了你的解决scheme来链接多个属性:

 public static string GetPropertyName<T>(Expression<Func<T>> propertyLambda) { MemberExpression me = propertyLambda.Body as MemberExpression; if (me == null) { throw new ArgumentException("You must pass a lambda of the form: '() => Class.Property' or '() => object.Property'"); } string result = string.Empty; do { result = me.Member.Name + "." + result; me = me.Expression as MemberExpression; } while (me != null); result = result.Remove(result.Length - 1); // remove the trailing "." return result; } 

用法:

 string name = GetPropertyName(() => someObject.SomeProperty.SomeOtherProperty); // returns "SomeProperty.SomeOtherProperty" 

基于已经在问题和这篇文章中的答案: https : //handcraftsman.wordpress.com/2008/11/11/how-to-get-c-property-names-without-magic-strings/ I我提出了解决这个问题的方法:

 public static class PropertyNameHelper { /// <summary> /// A static method to get the Propertyname String of a Property /// It eliminates the need for "Magic Strings" and assures type safety when renaming properties. /// See: http://stackoverflow.com/questions/2820660/get-name-of-property-as-a-string /// </summary> /// <example> /// // Static Property /// string name = PropertyNameHelper.GetPropertyName(() => SomeClass.SomeProperty); /// // Instance Property /// string name = PropertyNameHelper.GetPropertyName(() => someObject.SomeProperty); /// </example> /// <typeparam name="T"></typeparam> /// <param name="propertyLambda"></param> /// <returns></returns> public static string GetPropertyName<T>(Expression<Func<T>> propertyLambda) { var me = propertyLambda.Body as MemberExpression; if (me == null) { throw new ArgumentException("You must pass a lambda of the form: '() => Class.Property' or '() => object.Property'"); } return me.Member.Name; } /// <summary> /// Another way to get Instance Property names as strings. /// With this method you don't need to create a instance first. /// See the example. /// See: https://handcraftsman.wordpress.com/2008/11/11/how-to-get-c-property-names-without-magic-strings/ /// </summary> /// <example> /// string name = PropertyNameHelper((Firma f) => f.Firmenumsatz_Waehrung); /// </example> /// <typeparam name="T"></typeparam> /// <typeparam name="TReturn"></typeparam> /// <param name="expression"></param> /// <returns></returns> public static string GetPropertyName<T, TReturn>(Expression<Func<T, TReturn>> expression) { MemberExpression body = (MemberExpression)expression.Body; return body.Member.Name; } } 

还有一个testing,它也显示了实例和静态属性的用法:

 [TestClass] public class PropertyNameHelperTest { private class TestClass { public static string StaticString { get; set; } public string InstanceString { get; set; } } [TestMethod] public void TestGetPropertyName() { Assert.AreEqual("StaticString", PropertyNameHelper.GetPropertyName(() => TestClass.StaticString)); Assert.AreEqual("InstanceString", PropertyNameHelper.GetPropertyName((TestClass t) => t.InstanceString)); } } 

老问题,但这个问题的另一个答案是在使用CallerMemberNameAttribute的助手类中创build一个静态函数。

 public static string GetPropertyName([CallerMemberName] String propertyName = null) { return propertyName; } 

然后像这样使用它:

 public string MyProperty { get { Console.WriteLine("{0} was called", GetPropertyName()); return _myProperty; } } 

您可以使用StackTrace类来获取当前函数的名称(或者如果您将代码放在函数中,然后降级并获取调用函数)。

请参阅http://msdn.microsoft.com/zh-CN/library/system.diagnostics.stacktrace(VS.71).aspx

我一直在使用这个答案效果非常好: 从expression式<Func <TModel,TProperty>获取属性,作为string

我意识到我已经回答了这个问题。 我的其他答案唯一的好处是,它适用于静态属性。 我发现这个答案中的语法更有用,因为你不必创build你想要反映的types的variables。

使用已经为我的具体用例提出的解决scheme,我遇到了一些困难,但是最终得出结论。 我不认为我的具体案例值得一个新的问题,所以我张贴我的解决scheme在这里作为参考。 (这个问题是非常密切的,并提供一个与我的类似案件的其他人的解决scheme)。

我结束的代码如下所示:

 public class HideableControl<T>: Control where T: class { private string _propertyName; private PropertyInfo _propertyInfo; public string PropertyName { get { return _propertyName; } set { _propertyName = value; _propertyInfo = typeof(T).GetProperty(value); } } protected override bool GetIsVisible(IRenderContext context) { if (_propertyInfo == null) return false; var model = context.Get<T>(); if (model == null) return false; return (bool)_propertyInfo.GetValue(model, null); } protected void SetIsVisibleProperty(Expression<Func<T, bool>> propertyLambda) { var expression = propertyLambda.Body as MemberExpression; if (expression == null) throw new ArgumentException("You must pass a lambda of the form: 'vm => vm.Property'"); PropertyName = expression.Member.Name; } } public interface ICompanyViewModel { string CompanyName { get; } bool IsVisible { get; } } public class CompanyControl: HideableControl<ICompanyViewModel> { public CompanyControl() { SetIsVisibleProperty(vm => vm.IsVisible); } } 

对我来说重要的一点是,在CompanyControl类中,编译器只允许我select一个ICompanyViewModel的布尔属性,这使得其他开发人员更容易做到。

我的解决scheme和接受的答案之间的主要区别是我的类是通用的,我只想匹配布尔型的genericstypes的属性。

这是我如何实现它,其背后的原因是,如果你想从它的成员名称类不是静态的,那么你需要创build一个实例,然后获取成员的名称。 所以通用这里来帮助

 public static string GetName<TClass>(Expression<Func<TClass, object>> exp) { MemberExpression body = exp.Body as MemberExpression; if (body == null) { UnaryExpression ubody = (UnaryExpression)exp.Body; body = ubody.Operand as MemberExpression; } return body.Member.Name; } 

用法就是这样

 var label = ClassExtension.GetName<SomeClass>(x => x.Label); //x is refering to 'SomeClass'