C# 通过反射将访问器Func加载到字典中
背景:用户应该能够尽可能高效合理地选择DB表/模型/类,并过滤/排序/显示其所有公共属性 反射API可以查询这些名称,但我想知道,这些访问是否可以通过这种方式存储并变得更有效 这个例子展示了如何实现,但是在每次访问时,它都会在func中查询反射apiC# 通过反射将访问器Func加载到字典中,c#,system.reflection,C#,System.reflection,背景:用户应该能够尽可能高效合理地选择DB表/模型/类,并过滤/排序/显示其所有公共属性 反射API可以查询这些名称,但我想知道,这些访问是否可以通过这种方式存储并变得更有效 这个例子展示了如何实现,但是在每次访问时,它都会在func中查询反射api public class TestClass // the Model or Table { public int Id { get; set; } public string Name { get; set; } } publi
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小表达式树,该树将参数对象强制转换为正确的类型TestClass(在本例中),调用属性的getter并将结果转换为对象。请注意,如果您按照建议执行,您将在C端筛选行。。。您不会生成使用WHERE的SQL查询。您的C代码将接收表中的所有行,然后对它们进行筛选:-一般来说,如何正确地执行此操作取决于您如何查询数据库。。。如果将Ado.NET DbConnection或SqlConnection与DbCommand或SqlCommand一起使用,并使用字符串编写查询,则有一组解决方案。如果您使用实体框架,Linq to SQL,NHibernate???还有其他的解决方案,很好。不幸的是,我需要将记录加载到内存中,因为我必须在筛选之前对它们进行预处理,并且我无法更改基础表表示或将预处理的版本存储在另一个表中。我很好奇这是否可能,比如“C函数的存储过程”