(См. ниже решения, я создал использование ответа, который я принял),
Я пытаюсь улучшить пригодность для обслуживания некоторого кода, включающего отражение. Приложение имеет интерфейс Remoting.NET, выставляющий (среди прочего) метод под названием, Выполняются для доступа к частям приложения, не включенного в его опубликованный удаленный интерфейс.
Вот то, как приложение определяет свойства (статический в этом примере), которые предназначены, чтобы быть доступными через, Выполнитесь:
RemoteMgr.ExposeProperty("SomeSecret", typeof(SomeClass), "SomeProperty");
Таким образом, удаленный пользователь мог звонить:
string response = remoteObject.Execute("SomeSecret");
и приложение использовало бы отражение для нахождения SomeClass. SomeProperty и возвращают его значение как строку.
К сожалению, если кто-то переименовывает SomeProperty и забывает изменять 3-й parm ExposeProperty (), он повреждает этот механизм.
Мне нужно к эквиваленту:
SomeClass.SomeProperty.GetTheNameOfThisPropertyAsAString()
для использования в качестве, 3-й parm в ExposeProperty, о котором заботились бы настолько осуществляющие рефакторинг инструменты, переименовывает.
Существует ли способ сделать это?Заранее спасибо.
Хорошо, вот то, что я закончил тем, что создал (основанный на ответе, который я выбрал и вопрос, на который он сослался):
// <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);
Теперь с этой прохладной возможностью, пора упростить метод ExposeProperty. Полировка ручек двери является опасной работой...
Спасибо все.
Используя GetMemberInfo отсюда: Получив имя свойства из лямбда-выражения , вы можете сделать что-то вроде этого:
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);
}
}
Вы можете использовать Reflection для получения фактических имен свойств.
http://www.csharp-examples.net/reflection-property-names/
Если вам нужен способ присвоить свойству "строковое имя", почему бы вам не написать атрибут, над которым вы можете отразить, чтобы получить строковое имя?
[StringName("MyStringName")]
private string MyProperty
{
get { ... }
}
Класс PropertyInfo должен помочь вам в этом, если я правильно понимаю.
PropertyInfo [] propInfos = typeof (ReflectedType) .GetProperties ();
propInfos.ToList (). ForEach (p =>
Console.WriteLine (string.Format ("Имя свойства: {0}", p.Name));
Это то, что вам нужно?
Вы можете использовать класс StackTrace для получения имени текущей функции (или, если вы поместите код в функцию, то спуститесь на уровень ниже и получите вызывающую функцию).
См. http://msdn.microsoft.com/en-us/library/system.diagnostics.stacktrace(VS.71).aspx
Есть известный хак для извлечения его из лямбда-выражения (это из класса PropertyObserver, Джош Смит, в его MVVM foundation):
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;
}
Извините, не хватает контекста. Это была часть более крупного класса, где TPropertySource
- класс, содержащий свойство. Вы могли бы сделать функцию общей в TPropertySource, чтобы извлечь ее из класса. Я рекомендую взглянуть на полный код из MVVM Foundation.