通过反射为字典加载登录器弹性



背景:用户应该能够尽可能有效地合理地选择DB-table/model/class和filter/sort/sort/dishere there public属性。

可以通过Reflection-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);
}

i创建一个不同的小表达树,将参数对象投射到"正确"类型(在这种情况下为TestClass),调用属性的Getter,然后将结果转换为object

最新更新