创建动态函数< T,TResult>。来自对象 [英] Create Dynamic Func<T, TResult> from Object

查看:64
本文介绍了创建动态函数< T,TResult>。来自对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个criteria对象,如果该属性的值不为null,我将其中的每个属性都转换为一个func。 c>公共类TestClassCriteria
{
公共布尔? ColumnA {get;组; }
公共布尔? ColumnB {get;组; }
}

这是我到目前为止的内容,但是我很确定自己是没有正确定义lambda。这就是我想要实现的目标。 funcs.Add(x => x.ColumnA ==条件.ColumnA)

  var属性=条件.GetType()。GetProperties(); 
var funcs = new List< Func< dynamic,bool>>();

foreach(属性中的var属性)
{
var propertyName = property.Name;

funcs.Add(x => x.GetType()。GetProperty(propertyName).Name ==条件.GetType()。GetProperty(propertyName).Name);
}

它没有崩溃或引起任何错误,它只是无法正常工作。 / p>

您能提供的任何帮助将不胜感激。

解决方案

您想要这样的东西吗? GetCriteriaFunctions< TEntity,TCriteria>()
{
varcriteriasFunctions = new List< Func< TEntity,TCriteria,bool>();

//搜索条件
的可空属性varcriteriaProperties = typeof(TCriteria)
.GetProperties()
。where(p => p.PropertyType。 IsGenericType& p.PropertyType.GetGenericTypeDefinition()== typeof(Nullable<>));

foreach(criteriaProperties中的var属性)
{
//这是实体参数
var entityParameterExpression = Expression.Parameter(typeof(TEntity));
//这是标准参数
var条件ParameterExpression = Expression.Parameter(typeof(TCriteria));
//这是标准属性访问: criteria.SomeProperty
varcriteriaPropertyExpression = Expression.Property(criteriaParameterExpression,property);
//测试标准属性和实体属性之间是否相等;
//注意,criteria属性应首先转换;
// //此代码也假定实体和条件属性具有相同的名称
var testingForEqualityExpression = Expression.Equal(
Expression.Convert(criteriaPropertyExpression,property.PropertyType.GetGenericArguments() [0]),
Expression.Property(entityParameterExpression,property.Name));

//条件。SomeProperty== null? true:(((EntityPropertyType)criteria.SomeProperty == entity.SomeProperty)
var体= Expression.Condition(
Expression.Equal(criteriaPropertyExpression,Expression.Constant(null)),
Expression。常量(true),
testingForEqualityExpression);

//让我们将lambda编译为方法
var条件函数= Expression.Lambda< Func< TEntity,TCriteria,bool>(body,EntityParameterParameterion,criteriaParameterParameterExpression).Compile();

criteriaFunctions.Add(criteriaFunction);
}

返回条件函数;
}

样本实体和样本标准:

 类CustomerCriteria 
{
public int?年龄{get;组; }
公共布尔? IsNew {得到;组; }
}

类客户
{
公共字符串名称{get;组; }
public int年龄{get;组; }
public bool IsNew {get;组; }
}

用法:

  var条件函数= GetCriteriaFunctions< Customer,CustomerCriteria>(); 
var customer1 =新客户{名称= John,年龄= 35,IsNew = false};
var customer2 =新客户{名称= Mary,年龄= 27,IsNew = true};
var条件1 =新的CustomerCriteria {年龄= 35};
var条件2 =新的CustomerCriteria {IsNew = true};

Console.WriteLine( Is match:{0},criteriaFunctions.All(f => f(customer1,criteria1)));
Console.WriteLine( Is match:{0},criteriaFunctions.All(f => f(customer2,criteria1)));
Console.WriteLine( Is match:{0},criteriaFunctions.All(f => f(customer1,criteria2)));
Console.WriteLine( Is match:{0},criteriaFunctions.All(f => f(customer2,criteria2)));

此代码不是使用动态代码,而是使用强类型成员访问,因此,您可以缓存列表每对实体-条件和测试实例的条件匹配速度更快。


I have a criteria object in which I was to turn each property into a func, if it's value isn't null.

public class TestClassCriteria
{
    public bool? ColumnA { get; set; }
    public bool? ColumnB { get; set; }
}

This is what I have thus far, but I am pretty sure I am not defining the lambda correct. This is what I trying to achieve. funcs.Add(x => x.ColumnA == criteria.ColumnA).

var properties = criteria.GetType().GetProperties();
var funcs = new List<Func<dynamic, bool>>();

foreach (var property in properties)
{
    var propertyName = property.Name;

    funcs.Add(x => x.GetType().GetProperty(propertyName).Name == criteria.GetType().GetProperty(propertyName).Name);
}

It's not crashing or causing any error, it just isn't working.

Any help you can provide would be greatly appreciated.

解决方案

Do you want something like this?

    static List<Func<TEntity, TCriteria, bool>> GetCriteriaFunctions<TEntity, TCriteria>()
    {
        var criteriaFunctions = new List<Func<TEntity, TCriteria, bool>>();

        // searching for nullable properties of criteria
        var criteriaProperties = typeof(TCriteria)
            .GetProperties()
            .Where(p => p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>));

        foreach (var property in criteriaProperties)
        {
            // this is entity parameter
            var entityParameterExpression = Expression.Parameter(typeof(TEntity));
            // this is criteria parameter
            var criteriaParameterExpression = Expression.Parameter(typeof(TCriteria));
            // this is criteria property access: "criteria.SomeProperty"
            var criteriaPropertyExpression = Expression.Property(criteriaParameterExpression, property);
            // this is testing for equality between criteria property and entity property;
            // note, that criteria property should be converted first;
            // also, this code makes assumption, that entity and criteria properties have the same names
            var testingForEqualityExpression = Expression.Equal(
                Expression.Convert(criteriaPropertyExpression, property.PropertyType.GetGenericArguments()[0]), 
                Expression.Property(entityParameterExpression, property.Name));

            // criteria.SomeProperty == null ? true : ((EntityPropertyType)criteria.SomeProperty == entity.SomeProperty)
            var body = Expression.Condition(
                Expression.Equal(criteriaPropertyExpression, Expression.Constant(null)), 
                Expression.Constant(true),
                testingForEqualityExpression);

            // let's compile lambda to method
            var criteriaFunction = Expression.Lambda<Func<TEntity, TCriteria, bool>>(body, entityParameterExpression, criteriaParameterExpression).Compile();

            criteriaFunctions.Add(criteriaFunction);
        }

        return criteriaFunctions;
    }

Sample entity and sample criteria:

class CustomerCriteria
{
    public int? Age { get; set; }
    public bool? IsNew { get; set; }
}

class Customer
{
    public string Name { get; set; }
    public int Age { get; set; }
    public bool IsNew { get; set; }
}

Usage:

        var criteriaFunctions = GetCriteriaFunctions<Customer, CustomerCriteria>();
        var customer1 = new Customer { Name = "John", Age = 35, IsNew = false };
        var customer2 = new Customer { Name = "Mary", Age = 27, IsNew = true };
        var criteria1 = new CustomerCriteria { Age = 35 };
        var criteria2 = new CustomerCriteria { IsNew = true };

        Console.WriteLine("Is match: {0}", criteriaFunctions.All(f => f(customer1, criteria1)));
        Console.WriteLine("Is match: {0}", criteriaFunctions.All(f => f(customer2, criteria1)));
        Console.WriteLine("Is match: {0}", criteriaFunctions.All(f => f(customer1, criteria2)));
        Console.WriteLine("Is match: {0}", criteriaFunctions.All(f => f(customer2, criteria2)));

Instead of your code with dynamics, this code uses strongly typed member access, so, you could cache list of criteria for each pair "Entity - Criteria" and test instances form matching faster.

这篇关于创建动态函数&lt; T,TResult&gt;。来自对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆