如何在C#中使用Type数据

时间:2017-05-10 12:17:27

标签: c# lambda

我有以下几行:

var lambdaExpression = Expression.Lambda<Func<ClassOne, bool>>(eq, parameter);
var myList = db.ClassOne.Where(lambdaExpression).ToList();

我想让这些线条变得通用。我的尝试是这样的:

mytype = typeof(ClassOne);
var lambdaExpression = Expression.Lambda<Func<mytype, bool>>(eq, parameter);
var myList = db.mytype.Where(lambdaExpression).ToList();

但我明白了:

  

'mytype'是一个变量,但用作类型

  

'实体'不包含'mytype'的定义,也没有扩展名   方法'mytype'接受'Entities'类型的第一个参数可能是   发现(您是否缺少using指令或程序集引用?)

如您所见,我想通过变量传递ClassOne的名称。我怎样才能做到这一点?感谢。

2 个答案:

答案 0 :(得分:1)

这是我一直用来获得Expression<Func<type1, type2>>的方法。这是反思的力量:

        public static MethodInfo GetLambdaExpressionMethod(Type type1, Type type2)
        {
                return typeof(Expression).GetMethods().Where(x => x.Name == "Lambda").First()
                    .MakeGenericMethod(typeof(Func<,>).MakeGenericType(type1, type2));
        }

您可以使用它,如下所示:

var lambda = GetLambdaExpressionMethod(yourType, typeof(bool)).Invoke(null,
                    new object[] {
                        eq,
                        new ParameterExpression[] { parameter }
                    });

现在将lambda变量(现在是对象)转换为yourType的Expression<Func<yourType, bool>>

答案 1 :(得分:1)

非常简单:

public class ClassOne
{
    public int ID { get; set; }
}

然后我们可以:

public static class MyWhereHelper
{
    public static readonly MethodInfo WhereMethod = typeof(MyWhereHelper).GetMethod("Where", BindingFlags.Static | BindingFlags.Public);

    public static List<T> Where<T>(IQueryable<T> baseQuery, Expression<Func<T, bool>> where)
    {
        return baseQuery.Where(where).ToList();
    }
}

然后我们使用它:

// Sample data
var db = new
{
    Data = new[]
    {
        new ClassOne { ID = 1 },
        new ClassOne { ID = 2 },
        new ClassOne { ID = 3 },
    }.AsQueryable(),
};

var mytype = typeof(ClassOne);

// Real code begins here
var parameter = Expression.Parameter(mytype);

var eq = Expression.Equal(Expression.Property(parameter, "ID"), Expression.Constant(2));

// In truth lambdaExpression is Expression<Func<mytype, bool>>
LambdaExpression lambdaExpression = Expression.Lambda(eq, parameter);

// Search of mytype inside db
// We look for the property that is implementing IQueryable<mytype>
// We could lookup by name if the name is .mytype
var iqueryableMyType = typeof(IQueryable<>).MakeGenericType(mytype);
var prop = db.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public).Single(x => iqueryableMyType.IsAssignableFrom(x.PropertyType));

// db.mytype value
var propValue = prop.GetValue(db);

// MyWhereHelper.Where<mytype>
MethodInfo method = MyWhereHelper.WhereMethod.MakeGenericMethod(mytype);

var myList = (IEnumerable<object>)method.Invoke(null, new object[] { propValue, lambdaExpression });

我们使用反射来查找db.mytype并执行查询(请注意我们正在使用&#34;技巧&#34;此处:我们尝试将所有需要使用{{1}的内容放入在单个方法中使用泛型参数,并使用反射一次来执行该方法。显然,我是在谈论<mytype>)。

MyWhereHelper.Where<>内,所有内容都是强类型的。在MyWhereHelper.Where<>内,我们有一个MyWhereHelper.Where(即List<T>)。但是一旦我们退出List<mytype>,调用者就会在编译时再次知道MyWhereHelper.Where<> 的确切类型,因此它只能将结果操作为{{1} }(或再次使用反射来操纵它)