我有一个类似于这个的方法:
static string GetVariableName<T>(Expression<Func<T>> expression)
{
var body = expression.Body as MemberExpression;
return body.Member.Name;
}
给我变量名称。提到Reflection的每个人都说这对性能有害,所以我想缓存结果,这样每个var只能反映一次。例如:
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();
有什么想法吗?
答案 0 :(得分:2)
每个提到反思的人都说这对表现不利
当然,但在这种情况下,您已经拥有了lambda表达式中的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中所有强类型助手的工作方式。如果使用强类型lambda表达式版本,则不需要缓存任何内容。
答案 1 :(得分:1)
你应该可以做这样的事情......
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
答案 2 :(得分:0)
您是否考虑过使用属性?您可以反思模型一次,然后缓存这些结果。
[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);
}
}