通过反射将访问器 Func 加载到 Dictionary 中
Load accessor Func by reflection into Dictionary
背景:用户应该能够尽可能高效合理地选择一个DB-Table/Model/Class和filter/sort/display它的所有public属性。
名称可以通过反射查询-API,但我想知道,是否可以通过这种方式存储这些访问并提高效率?
这个例子展示了它是如何完成的,但是在每次访问时它都会查询函数中的反射-api。
public class TestClass // the Model or Table
{
public int Id { get; set; }
public string Name { get; set; }
}
public static void Main( string[] args )
{
var testClasses = new TestClass[] {
new TestClass { Id = 1 , Name = "1" } ,
new TestClass { Id = 2 , Name = "2" } ,
new TestClass { Id = 3 , Name = "3" } ,
};
var propertyInfos = typeof( TestClass ).GetProperties();
var map = new Dictionary<string,Func<object,object>>(); // Func<object,object> -> Func takes an instance of the class and return a public property
// load the map once
foreach( var propertyInfo in propertyInfos )
{
Func<object,object> func = x => propertyInfo.GetValue( x );
map.Add( propertyInfo.Name , func );
}
// get the names by user-input
var names = propertyInfos.Select( x => x.Name ).ToArray();
// load the properties by name
foreach( var testClass in testClasses )
{
Console.WriteLine( $"{testClass.Id} - {testClass.Name}" );
foreach( var name in names )
{
var func = map[ name ];
var value = func( testClass ); // this is 'bad' as it uses reflection every invokation
Console.WriteLine( $"\t{name} = {value}" );
}
}
}
我的问题是:这本词典可以吗
var map = new Dictionary<string,Func<object,object>> {
{ "Id" , x => ( x as TestClass ).Id } ,
{ "Name" , x => ( x as TestClass ).Name } ,
};
通过提供类型自动创建(并且不在每次调用时使用反射)?
您可以通过从每次调用中删除反射并只执行一次来获得一些东西:
var par = Expression.Parameter(typeof(object), "row");
// load the map once
foreach (var propertyInfo in propertyInfos)
{
Func<object, object> func = Expression.Lambda<Func<object, object>>(Expression.Convert(Expression.Property(Expression.Convert(par, propertyInfo.DeclaringType), propertyInfo), typeof(object)), par).Compile();
map.Add(propertyInfo.Name, func);
}
我创建了一个 vary small 表达式树,将参数对象转换为 "correct" 类型(在本例中为 TestClass
),调用 getter 的 属性并将结果转换为 object
.
背景:用户应该能够尽可能高效合理地选择一个DB-Table/Model/Class和filter/sort/display它的所有public属性。
名称可以通过反射查询-API,但我想知道,是否可以通过这种方式存储这些访问并提高效率?
这个例子展示了它是如何完成的,但是在每次访问时它都会查询函数中的反射-api。
public class TestClass // the Model or Table
{
public int Id { get; set; }
public string Name { get; set; }
}
public static void Main( string[] args )
{
var testClasses = new TestClass[] {
new TestClass { Id = 1 , Name = "1" } ,
new TestClass { Id = 2 , Name = "2" } ,
new TestClass { Id = 3 , Name = "3" } ,
};
var propertyInfos = typeof( TestClass ).GetProperties();
var map = new Dictionary<string,Func<object,object>>(); // Func<object,object> -> Func takes an instance of the class and return a public property
// load the map once
foreach( var propertyInfo in propertyInfos )
{
Func<object,object> func = x => propertyInfo.GetValue( x );
map.Add( propertyInfo.Name , func );
}
// get the names by user-input
var names = propertyInfos.Select( x => x.Name ).ToArray();
// load the properties by name
foreach( var testClass in testClasses )
{
Console.WriteLine( $"{testClass.Id} - {testClass.Name}" );
foreach( var name in names )
{
var func = map[ name ];
var value = func( testClass ); // this is 'bad' as it uses reflection every invokation
Console.WriteLine( $"\t{name} = {value}" );
}
}
}
我的问题是:这本词典可以吗
var map = new Dictionary<string,Func<object,object>> {
{ "Id" , x => ( x as TestClass ).Id } ,
{ "Name" , x => ( x as TestClass ).Name } ,
};
通过提供类型自动创建(并且不在每次调用时使用反射)?
您可以通过从每次调用中删除反射并只执行一次来获得一些东西:
var par = Expression.Parameter(typeof(object), "row");
// load the map once
foreach (var propertyInfo in propertyInfos)
{
Func<object, object> func = Expression.Lambda<Func<object, object>>(Expression.Convert(Expression.Property(Expression.Convert(par, propertyInfo.DeclaringType), propertyInfo), typeof(object)), par).Compile();
map.Add(propertyInfo.Name, func);
}
我创建了一个 vary small 表达式树,将参数对象转换为 "correct" 类型(在本例中为 TestClass
),调用 getter 的 属性并将结果转换为 object
.