[100分,CSDN8年老用户求助!]关于反射,泛型,Linq相关问题

yuandonghuia 2017-08-03 11:12:37
各位大神好久不见,这是玩CSDN的第八个年头了,白驹过隙啊!最近几年来干的事越来越杂,代码越写越少了.
但是最近又在设计一个框架遇到反射的一些问题.请教各位大神了.
PS.在我玩论坛的那几年,caozhy是比较常见的大神了,其他的都记不清名字了.
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
public class teatca
{
public string A { get; set; }
public string B { get; set; }
}

public class testc
{
public List<teatca> As { get; set; }
}
class Program
{
static void Main(string[] args)
{
testc cc = new testc();
var bb = cc.As;
var bbwhere = bb.Where(x => x.A == "aaa");
//第一个集合通过查询资料已经解决了,第二个实在是在网上查询不到解决方案才敢叨扰各位大神!
var bb1 = cc.GetType().GetProperty("As").GetValue(cc);
//我知道下面的写法不对,我就是想用反射的方法来实现linq语句,实现where 求各位大神!!!
//我就想让bbwhere1的值和bbwhere一样就可以
var bbwhere1 = bb1.GetType().GetGenericArguments().Where(x => x.GetProperty("A").GetValue(x).ToString() == "aaa");
Console.ReadLine();
}
}
}
...全文
455 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
yuandonghuia 2017-08-08
  • 打赏
  • 举报
回复
已经问到其他大神,用反射的方法应该能执行sql语句. 但是我也改变了架构思路,这里不用EF框架了. 谢谢各位大神结帖了. @hanjun0612 咱俩联系我另外给你开贴送分.

private static System.Reflection.MethodInfo getExpressionLambdaMethod()
        {
            foreach (var method in typeof(System.Linq.Expressions.Expression).GetMethods(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public))
            {
                if (method.IsGenericMethodDefinition && method.Name == "Lambda" && method.GetGenericArguments().Length == 1)
                {
                    var methodParameters = method.GetParameters();
                    if (methodParameters.Length == 2 && methodParameters[0].ParameterType == typeof(System.Linq.Expressions.Expression) && methodParameters[1].ParameterType == typeof(System.Linq.Expressions.ParameterExpression[]))
                    {
                        return method;
                    }
                }
            }
            throw new MissingMethodException();
        }
作者:肖进
链接:https://www.zhihu.com/question/63343132/answer/208187509
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

private static System.Reflection.MethodInfo getEnumerableWhereMethod()
        {
            foreach (var method in typeof(System.Linq.Enumerable).GetMethods(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public))
            {
                if (method.IsGenericMethodDefinition && method.Name == "Where" && method.GetGenericArguments().Length == 1)
                {
                    var methodParameters = method.GetParameters();
                    if (methodParameters.Length == 2 && methodParameters[0].ParameterType.IsGenericType && methodParameters[1].ParameterType.IsGenericType && methodParameters[0].ParameterType.GetGenericTypeDefinition() == typeof(System.Collections.Generic.IEnumerable<>) && methodParameters[1].ParameterType.GetGenericTypeDefinition() == typeof(Func<,>))
                    {
                        return method;
                    }
                }
            }
            throw new MissingMethodException();
        }
作者:肖进
链接:https://www.zhihu.com/question/63343132/answer/208187509
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

var bb1 = cc.GetType().GetProperty("As").GetValue(cc);
            Type[] types = bb1.GetType().GetGenericArguments();
            Type funcType = typeof(Func<,>).MakeGenericType(types[0], typeof(bool));
            System.Linq.Expressions.ParameterExpression[] parameters = new System.Linq.Expressions.ParameterExpression[] { System.Linq.Expressions.Expression.Parameter(types[0], "value") };
            var expression = getExpressionLambdaMethod().MakeGenericMethod(funcType).Invoke(null, new object[] { System.Linq.Expressions.Expression.Equal(System.Linq.Expressions.Expression.Property(parameters[0], types[0].GetProperty("A").GetGetMethod()), System.Linq.Expressions.Expression.Constant("aaa", typeof(string))), parameters });
            var func = typeof(System.Linq.Expressions.Expression<>).MakeGenericType(funcType).GetMethod("Compile", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public, null, new Type[0], null).Invoke(expression, null);
            var bbwhere1 = getEnumerableWhereMethod().MakeGenericMethod(types).Invoke(null, new object[] { bb1, func });
正怒月神 2017-08-08
  • 打赏
  • 举报
回复
引用 14 楼 yuandonghuia 的回复:
已经问到其他大神,用反射的方法应该能执行sql语句. 但是我也改变了架构思路,这里不用EF框架了. 谢谢各位大神结帖了. @hanjun0612 咱俩联系我另外给你开贴送分.

private static System.Reflection.MethodInfo getExpressionLambdaMethod()
        {
            foreach (var method in typeof(System.Linq.Expressions.Expression).GetMethods(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public))
            {
                if (method.IsGenericMethodDefinition && method.Name == "Lambda" && method.GetGenericArguments().Length == 1)
                {
                    var methodParameters = method.GetParameters();
                    if (methodParameters.Length == 2 && methodParameters[0].ParameterType == typeof(System.Linq.Expressions.Expression) && methodParameters[1].ParameterType == typeof(System.Linq.Expressions.ParameterExpression[]))
                    {
                        return method;
                    }
                }
            }
            throw new MissingMethodException();
        }
作者:肖进
链接:https://www.zhihu.com/question/63343132/answer/208187509
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

private static System.Reflection.MethodInfo getEnumerableWhereMethod()
        {
            foreach (var method in typeof(System.Linq.Enumerable).GetMethods(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public))
            {
                if (method.IsGenericMethodDefinition && method.Name == "Where" && method.GetGenericArguments().Length == 1)
                {
                    var methodParameters = method.GetParameters();
                    if (methodParameters.Length == 2 && methodParameters[0].ParameterType.IsGenericType && methodParameters[1].ParameterType.IsGenericType && methodParameters[0].ParameterType.GetGenericTypeDefinition() == typeof(System.Collections.Generic.IEnumerable<>) && methodParameters[1].ParameterType.GetGenericTypeDefinition() == typeof(Func<,>))
                    {
                        return method;
                    }
                }
            }
            throw new MissingMethodException();
        }
作者:肖进
链接:https://www.zhihu.com/question/63343132/answer/208187509
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

var bb1 = cc.GetType().GetProperty("As").GetValue(cc);
            Type[] types = bb1.GetType().GetGenericArguments();
            Type funcType = typeof(Func<,>).MakeGenericType(types[0], typeof(bool));
            System.Linq.Expressions.ParameterExpression[] parameters = new System.Linq.Expressions.ParameterExpression[] { System.Linq.Expressions.Expression.Parameter(types[0], "value") };
            var expression = getExpressionLambdaMethod().MakeGenericMethod(funcType).Invoke(null, new object[] { System.Linq.Expressions.Expression.Equal(System.Linq.Expressions.Expression.Property(parameters[0], types[0].GetProperty("A").GetGetMethod()), System.Linq.Expressions.Expression.Constant("aaa", typeof(string))), parameters });
            var func = typeof(System.Linq.Expressions.Expression<>).MakeGenericType(funcType).GetMethod("Compile", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public, null, new Type[0], null).Invoke(expression, null);
            var bbwhere1 = getEnumerableWhereMethod().MakeGenericMethod(types).Invoke(null, new object[] { bb1, func });
看起来有点复杂,反射了表达式树Expressions
threenewbee 2017-08-05
  • 打赏
  • 举报
回复
http://ideone.com/OzzJj3
yuandonghuia 2017-08-05
  • 打赏
  • 举报
回复
引用 12 楼 caozhy 的回复:
http://ideone.com/OzzJj3
曹大神,我现在的需求如下: 已知字符串"classA" " PropertyB" B属性的类型为集合 "123" 从B属性的集合里面调出符合条件的集合 C 目前已经能做到的,通过字符串的"classA" 反射生成A类的实例, 通过" PropertyB"的字符串,从A的实例中取得属性B 但是第三步,我知道B是一个集合,使用where方法取得符合条件某属性="123"的集合C 现在是第三布实现不了,我知道B是集合,编译器不知道,所以不知道着这种方法下如何调用where方法实现求得符合条件的B的集合子集 顺便提一句,B是自动生成的,不能在B中写方法,只能用扩展方法求B的子集. 您写的代码,好像只是求了一下属性,但是好像也无法实现求where方法... 其实我现在感觉好像实现不了,打算用另外一个框架了,但是还是想知道,C#目前是否能实现我的需求. 叨扰大神了.
yuandonghuia 2017-08-03
  • 打赏
  • 举报
回复
引用 3 楼 ilikeff8 的回复:
搜动态linq
到linq那步就好说了 我大概查了查,所谓的动态linq是where后面的条件用字符串来写. 但是我的问题是在前面 .where都出不来 我知道这玩意是个集合,但是编译器不知道啊
ilikeff8 2017-08-03
  • 打赏
  • 举报
回复
搜动态linq
yuandonghuia 2017-08-03
  • 打赏
  • 举报
回复
引用 1 楼 hanjun0612 的回复:
必须用反射,而不尝试表达式树Expression吗?
感谢版主大大关注,并不见得非得用反射, 我这个函数的入参必须是string类型的,(涉及到到通用接口,必须string类型) 我根据入参来动态实现从一个大类里面取一个未知的属性(其实就是ef的具体的表) 而此属性是一个集合, 我需要在动态获取此类型的情况下,使用linq语句实现where操作. 只要实现了这个目的,并不拘泥与任何具体的技术细节. 我试过直接把反射过来的类型强制转换为List<object> 这样是报错的. 我个人认为,现在的难点是如何把一个object类型,通过一些方法,转化为linq可以处理的 类型,然后才能进行下一步操作 不知道您所描述的表达式树,能否实现 我贴出的代码可以直接运行,您直接改下面的代码,然后 JsonConvert.SerializeObject(); 只要您贴出的结果和 bbwhere 转化过来的json串一样,技能解决我的问题. 劳烦大神了.
正怒月神 2017-08-03
  • 打赏
  • 举报
回复
必须用反射,而不尝试表达式树Expression吗?
yuandonghuia 2017-08-03
  • 打赏
  • 举报
回复
首先感谢版主大人的热心交流,我一定单开帖子给您来个3~500百分,不成敬意.
引用 10 楼 hanjun0612 的回复:
当var bbwhere = bb.Where(x => x.A == "aaa"); 这样是不会取出数据的。IQueryable 当var bbwhere = bb.Where(x => x.A == "aaa").ToList()会取出数据,这是一个IEnumerable 我更想知道的是 对 上面两个例子中 foreach bb的时候,是否取数据,bb是Iqueryable 因为用动态类型dynamic 的时候,必须用foreach,像你上面给我的例子一样. foreach (var item in bb) { //这里对item做一些处理. } 其实我在想,如果你用泛型和表达式树,那真的这个问题迎刃而解。 如果你的框架还没有使用,那我觉得还是改改吧。如果已经启用了,那也没办法,只能硬着头皮解决了 http://blog.csdn.net/hanjun0612/article/details/62887466
还好框架正在设计阶段,现在就是在探索,找到一个更好点的解决方案. 我看你发的博客了,我没看出来如何解决我的问题. 我这个其实是个web的接口,是JavaScript调用的,所以入参只能用string,我不知道这里怎么使用泛型来过渡 我试过,在给泛型函数的类型赋值的时候,必须直接写类型,不能用type.gettype(""""); 其实我觉得我这个需求,更想是在entityframework外层,又套上了一层sql.....因为入参是从JavaScript来的,只能是string.
正怒月神 2017-08-03
  • 打赏
  • 举报
回复
引用 8 楼 yuandonghuia 的回复:
我甚至在想,如果实在不行,这块就不用EF了,还是用sql语句直接从数据库取的方法了.但是还是想再试试.
当var bbwhere = bb.Where(x => x.A == "aaa"); 这样是不会取出数据的。IQueryable 当var bbwhere = bb.Where(x => x.A == "aaa").ToList()会取出数据,这是一个IEnumerable 其实我在想,如果你用泛型和表达式树,那真的这个问题迎刃而解。 如果你的框架还没有使用,那我觉得还是改改吧。如果已经启用了,那也没办法,只能硬着头皮解决了 http://blog.csdn.net/hanjun0612/article/details/62887466
yuandonghuia 2017-08-03
  • 打赏
  • 举报
回复
引用 5 楼 starfd 的回复:
caozhy 还在,你可以@caozhy
10星大版主,您也给看看呗,你们都是高手呀. PS,我点引用点错了,给了你一板砖,还不能取消,抱歉
yuandonghuia 2017-08-03
  • 打赏
  • 举报
回复
引用 7 楼 hanjun0612 的回复:
你试试动态类型来获取吧,不过动态类型无法使用Linq。 但是对于你的需求来说,应该是能满足的。
static void Main(string[] args)
        {
            testc cc = new testc();
            cc.As = new List<teatca>() { new teatca() { A = "aaa", B = "2" } };
            var bb = cc.As;
            var bbwhere = bb.Where(x => x.A == "aaa");
            //第一个集合通过查询资料已经解决了,第二个实在是在网上查询不到解决方案才敢叨扰各位大神!
            dynamic bb1 = cc.GetType().GetProperty("As").GetValue(cc);
            //我知道下面的写法不对,我就是想用反射的方法来实现linq语句,实现where 求各位大神!!!
            //我就想让bbwhere1的值和bbwhere一样就可以

            foreach (var item in bb1)
            {
                var r = item.GetType().GetProperty("A").GetValue(item);
                Console.WriteLine(r);
            }
            Console.ReadLine();
        }
感谢,您这样确实可以,昨天我用了这种方法了,这种方法确实是种选择. 我必须跟您说实际问题了. 我用的是entityframework 客户端将他们要取的表名和where条件通过制定好的字符串传递过来. 我不想用switch的笨方法将所有的表名都case一遍,所以想用反射的方法实现. 我虽然没有仔细讲究过EF的原理,但是我印象中,如果EF中你用了 dbEntities ge = new dbEntities(); var tableA=ge.tableA; foreach(tableA) 的话,如果tableA中的数据量比较大的话,相当于是一下子把表A中所有的数据都取出来了吧?所以考虑到效率问题, 请问版主,我这里说的效率问题是否真的存在? 我没有实际测试,只是凭借印象觉得有效率问题, 没用您这种方法. 不过能喝大版主思路一致,不胜荣幸. 我甚至在想,如果实在不行,这块就不用EF了,还是用sql语句直接从数据库取的方法了.但是还是想再试试.
正怒月神 2017-08-03
  • 打赏
  • 举报
回复
你试试动态类型来获取吧,不过动态类型无法使用Linq。 但是对于你的需求来说,应该是能满足的。
static void Main(string[] args)
        {
            testc cc = new testc();
            cc.As = new List<teatca>() { new teatca() { A = "aaa", B = "2" } };
            var bb = cc.As;
            var bbwhere = bb.Where(x => x.A == "aaa");
            //第一个集合通过查询资料已经解决了,第二个实在是在网上查询不到解决方案才敢叨扰各位大神!
            dynamic bb1 = cc.GetType().GetProperty("As").GetValue(cc);
            //我知道下面的写法不对,我就是想用反射的方法来实现linq语句,实现where 求各位大神!!!
            //我就想让bbwhere1的值和bbwhere一样就可以

            foreach (var item in bb1)
            {
                var r = item.GetType().GetProperty("A").GetValue(item);
                Console.WriteLine(r);
            }
            Console.ReadLine();
        }
正怒月神 2017-08-03
  • 打赏
  • 举报
回复
你意思是,你们有一个大类,里面都是各种List<T>对象。 然后传递一个 T的字符串名称? 那可以修改成泛型吗?
  • 打赏
  • 举报
回复
caozhy 还在,你可以@caozhy

110,499

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧