Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 通过反射将访问器Func加载到字典中_C#_System.reflection - Fatal编程技术网

C# 通过反射将访问器Func加载到字典中

C# 通过反射将访问器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

背景:用户应该能够尽可能高效合理地选择DB表/模型/类,并过滤/排序/显示其所有公共属性

反射API可以查询这些名称,但我想知道,这些访问是否可以通过这种方式存储并变得更有效

这个例子展示了如何实现,但是在每次访问时,它都会在func中查询反射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小表达式树,该树将参数对象强制转换为正确的类型TestClass(在本例中),调用属性的getter并将结果转换为对象。

请注意,如果您按照建议执行,您将在C端筛选行。。。您不会生成使用WHERE的SQL查询。您的C代码将接收表中的所有行,然后对它们进行筛选:-一般来说,如何正确地执行此操作取决于您如何查询数据库。。。如果将Ado.NET DbConnection或SqlConnection与DbCommand或SqlCommand一起使用,并使用字符串编写查询,则有一组解决方案。如果您使用实体框架,Linq to SQL,NHibernate???还有其他的解决方案,很好。不幸的是,我需要将记录加载到内存中,因为我必须在筛选之前对它们进行预处理,并且我无法更改基础表表示或将预处理的版本存储在另一个表中。我很好奇这是否可能,比如“C函数的存储过程”