Кеш отражает имена свойств - PullRequest
1 голос
/ 09 января 2012

У меня есть метод, похожий на этот:

static string GetVariableName<T>(Expression<Func<T>> expression)
{
    var body = expression.Body as MemberExpression;

    return body.Member.Name;
}

, который дает мне имена переменных.Все, кто упоминает Reflection, говорят, что это плохо для производительности, поэтому я хочу кешировать результат, чтобы отражение могло происходить только один раз для каждой переменной.Пример:

GetVariableName(() => Model.Field1) // Does Reflection.
GetVariableName(() => Model.Field2) // Does Reflection.
GetVariableName(() => Model.Field1) // Uses Cache.
GetVariableName(() => Model.Field2) // Uses Cache.

Я использую этот Util для регистрации параметров и хочу начать использовать его для создания JQuery селекторов в Asp.net Mvc3 приложении

$('#'+ @(GetVariableName(()=> Model.FieldName))).Val();

Есть идеи?

Ответы [ 3 ]

2 голосов
/ 09 января 2012

Все, кто упоминает Reflection, говорят, что это плохо для производительности

Конечно, но в этом случае у вас уже есть MemberInfo из лямбда-выражения. Компилятор уже построил дерево выражений. Вам не нужно извлекать его, используя отражение, которое является медленным. Что было бы дорого, так это:

static string GetVariableName(string expression)
{
    // use reflection to find the property given the string and once you have the property
    // get its name
    ...
}

Так работают все строго типизированные помощники в ASP.NET MVC. Вам не нужно ничего кэшировать, если вы используете строго типизированную версию лямбда-выражения.

1 голос
/ 09 января 2012

Вы должны быть в состоянии сделать что-то вроде этого ...

class Foo {

    public Foo() {
        m_Field1Name = new Lazy<string>(() => GetVariableName(() => Field1));
        m_Field2Name = new Lazy<string>(() => GetVariableName(() => Field2));
    }

    public int Field1 { get; set; }
    public int Field2 { get; set; }

    public string Field1Name {
        get {
            return m_Field1Name.Value;
        }
    }
    readonly Lazy<string> m_Field1Name;

    public string Field2Name {
        get {
            return m_Field2Name.Value;
        }
    }
    readonly Lazy<string> m_Field2Name;

    public static string GetVariableName<T>(Expression<Func<T>> expression) {
        var body = expression.Body as MemberExpression;
        return body.Member.Name;
    }

}

Сравнительный анализ кэшированных имен и некешированных показывает существенную разницу ...

class Program {

    static void Main(string[] args) {

        var foo = new Foo();

        const int count = 1000000;
        var sw = new Stopwatch();

        sw.Restart();
        for (int i = 0; i < count; ++i) {
            string name1 = foo.Field1Name;
            string name2 = foo.Field2Name;
        }
        sw.Stop();
        Console.Write("Cached:\t\t");
        Console.WriteLine(sw.Elapsed);

        sw.Restart();
        for (int i = 0; i < count; ++i) {
            string name1 = Foo.GetVariableName(() => foo.Field1);
            string name2 = Foo.GetVariableName(() => foo.Field2);
        }
        sw.Stop();
        Console.Write("Non-cached:\t");
        Console.WriteLine(sw.Elapsed);

    }

}

Это печатает:

Cached:     00:00:00.0176370
Non-cached: 00:00:12.9247333
0 голосов
/ 09 января 2012

Рассматривали ли вы использование атрибутов? Вы могли бы поразмышлять над моделью один раз и вместо этого кэшировать эти результаты.

[AttributeUsage(AttributeTargets.Property, AllowMultiple= false)]
class JQueryFieldNameAttribute : Attribute {

    public string Name { get; private set; }

    public JQueryFieldNameAttribute(string name)
    {
        Name = name;
    }
}

class Model {
    [JQueryFieldName("#clientid")]
    public string Foo { get; set; }
}

void Main()
{
    var type = typeof(Model);

    var attributes = type.GetProperties()
                         .SelectMany (t => t.GetCustomAttributes(typeof(JQueryFieldNameAttribute), true));

    var cache = new Dictionary<int, IEnumerable<JQueryFieldNameAttribute>>();

    // Cache results for this type only
    cache.Add(type.GetHashCode(), attributes);

    foreach (JQueryFieldNameAttribute a in attributes)
    {
        Console.WriteLine (a.Name);
    }   
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...