Получить имя свойства в виде строки - PullRequest
179 голосов
/ 12 мая 2010

(см. Ниже решение, которое я создал, используя ответ, который я принял)

Я пытаюсь улучшить удобство сопровождения некоторого кода, связанного с отражением. Приложение имеет интерфейс .NET Remoting, который предоставляет (помимо прочего) метод Execute для доступа к частям приложения, не включенным в опубликованный удаленный интерфейс.

Вот как приложение определяет свойства (статические в этом примере), которые должны быть доступны через Execute:

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

Чтобы удаленный пользователь мог позвонить:

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

и приложение будет использовать отражение, чтобы найти SomeClass.SomeProperty и вернуть его значение в виде строки.

К сожалению, если кто-то переименует SomeProperty и забудет изменить третий параметр ExposeProperty (), это нарушит этот механизм.

Мне нужно эквивалент:

SomeClass.SomeProperty.GetTheNameOfThisPropertyAsAString()

для использования в качестве третьего параметра в 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. Полировка дверных ручек - опасная работа ...

Спасибо всем.

Ответы [ 13 ]

0 голосов
/ 19 декабря 2016

У меня были некоторые трудности с использованием решений, уже предложенных для моего конкретного случая использования, но в конце концов я понял это. Я не думаю, что мой конкретный случай достоин нового вопроса, поэтому я публикую свое решение здесь для справки. (Это очень тесно связано с вопросом и предоставляет решение для всех, кто имеет аналогичный случай с моим).

Код, с которым я столкнулся, выглядит следующим образом:

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 компилятор позволяет мне выбирать логическое свойство ICompanyViewModel, что упрощает его разработку другими разработчиками.

Основное различие между моим решением и принятым ответом состоит в том, что мой класс является универсальным, и я хочу сопоставлять только свойства универсального типа, которые являются логическими.

0 голосов
/ 27 августа 2015

Я использовал этот ответ с большим эффектом: Получите свойство в виде строки из выражения >

Я понимаю, что уже ответил на этот вопрос некоторое время назад. Единственное преимущество, которое дает другой мой ответ - это то, что он работает для статических свойств. Я нахожу синтаксис в этом ответе гораздо более полезным, поскольку вам не нужно создавать переменную того типа, который вы хотите отобразить.

0 голосов
/ 12 мая 2010

Вы можете использовать класс StackTrace, чтобы получить имя текущей функции (или, если вы поместите код в функцию, затем уменьшите уровень и получите вызывающую функцию).

См. http://msdn.microsoft.com/en-us/library/system.diagnostics.stacktrace(VS.71).aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...