我有一个类似于这个的方法:
static string GetVariableName<T>(Expression<Func<T>> expression)
{
var body = expression.Body as MemberExpression;
return body.Member.Name;
}
这给了我变量的名字。每个提到反射的人都说这对性能不好,所以我想缓存结果,这样每个变量只能发生一次反射。示例:
GetVariableName(() => Model.Field1) // Does Reflection.
GetVariableName(() => Model.Field2) // Does Reflection.
GetVariableName(() => Model.Field1) // Uses Cache.
GetVariableName(() => Model.Field2) // Uses Cache.
我正在使用这个Util来记录参数,我想开始使用它在Asp.net Mvc3
应用程序中生成JQuery
选择器
$('#'+ @(GetVariableName(()=> Model.FieldName))).Val();
有什么想法吗?
每个提到反射的人都说这对的性能不利
当然,但在本例中,您已经拥有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表达式版本,则不需要缓存任何内容。
你应该能够做这样的事情。。。
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:tt");
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
您是否考虑过使用属性?您可以对模型进行一次反思,然后缓存这些结果。
[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);
}
}