C# 我如何使用Where<;T>;编译时T未知时的扩展方法

C# 我如何使用Where<;T>;编译时T未知时的扩展方法,c#,linq,entity-framework,lambda,generic-collections,C#,Linq,Entity Framework,Lambda,Generic Collections,我正在使用JSON编写C#MVC应用程序,并尝试使用EF将JSON检索回数据库 不幸的是,我无法让这样的代码工作: IEnumerable<object> NewValueSubCollection = (IEnumerable<object>)NewValue.GetType().GetProperty(col.Name).GetValue(NewValue, null); //Where col is a property of an object of type (

我正在使用JSON编写C#MVC应用程序,并尝试使用EF将JSON检索回数据库

不幸的是,我无法让这样的代码工作:

IEnumerable<object> NewValueSubCollection = (IEnumerable<object>)NewValue.GetType().GetProperty(col.Name).GetValue(NewValue, null);
//Where col is a property of an object of type (IEnumerable<???>)

foreach (var line in ((IEnumerable<object>)col.GetValue(originalEntity, null)).ToList<object>())
{
    Type lineType = ObjectContext.GetObjectType(line.GetType());
    var lineEntitySet = context.GetEntitySet(lineType);
    EntityKey lineKey = context.CreateEntityKey(lineEntitySet.Name, line);
    if (NewValueSubCollection.Where(lineKey).Count() == 0) //See bellow
    context.DeleteObject(line);
}

在第一个示例中,您的
NewValueSubCollection
静态类型为
IEnumerable
,因此您的参数化类型
T
object
,当您编译表达式时,它会尝试查找对象类上的属性,从而找到异常

同样,您的
o.Where(…)
也无法工作,因为
Where
扩展方法是在
IEnumerable
上定义的,并且这些方法在编译时是静态解析的


恐怕您必须通过反射调用
Where
方法,您可能会在这里找到一些帮助:

在第一个示例中,您的
NewValueSubCollection
静态类型为
IEnumerable
,因此您的参数化类型
T
对象,当编译表达式时,它会尝试查找对象类上的属性,从而查找异常

同样,您的
o.Where(…)
也无法工作,因为
Where
扩展方法是在
IEnumerable
上定义的,并且这些方法在编译时是静态解析的


我担心您必须通过反射调用
Where
方法,您可能会在这里找到一些帮助:

您需要动态访问此方法,但您可以使用“dynamic”关键字避免反射带来的一些麻烦

因此:

NewValueSubCollection.Where(lineKey).Count() == 0
变成这样:

NewValueSubCollection.Cast<dynamic>().Where(d => lineKey(d)).Count() == 0
NewValueSubCollection.Cast()。其中(d=>lineKey(d)).Count()==0
或者(如果枚举没有副作用,则更简单、更有效):

!NewValueSubCollection.Cast().Any(d=>lineKey(d))

一个简单的概念验证程序:

class Program
{
    static void Main(string[] args)
    {
        var list = new List<string>();
        IEnumerable<object> objects = list;
        Func<string, bool> func = s => s.Contains("x");

        list.Add("Test");
        list.Add("x");
        list.Add("mux");
        foreach (var item in objects.Cast<dynamic>().Where(d => func(d)))
            Console.WriteLine(item);
        Console.ReadKey();
    }
}
类程序
{
静态void Main(字符串[]参数)
{
var list=新列表();
IEnumerable对象=列表;
Func Func=s=>s.Contains(“x”);
列表。添加(“测试”);
列表。添加(“x”);
列表。添加(“mux”);
foreach(objects.Cast()中的var项,其中(d=>func(d)))
控制台写入线(项目);
Console.ReadKey();
}
}

您需要动态地访问此文件,但使用“dynamic”关键字可以避免一些令人头痛的反射问题

因此:

NewValueSubCollection.Where(lineKey).Count() == 0
变成这样:

NewValueSubCollection.Cast<dynamic>().Where(d => lineKey(d)).Count() == 0
NewValueSubCollection.Cast()。其中(d=>lineKey(d)).Count()==0
或者(如果枚举没有副作用,则更简单、更有效):

!NewValueSubCollection.Cast().Any(d=>lineKey(d))

一个简单的概念验证程序:

class Program
{
    static void Main(string[] args)
    {
        var list = new List<string>();
        IEnumerable<object> objects = list;
        Func<string, bool> func = s => s.Contains("x");

        list.Add("Test");
        list.Add("x");
        list.Add("mux");
        foreach (var item in objects.Cast<dynamic>().Where(d => func(d)))
            Console.WriteLine(item);
        Console.ReadKey();
    }
}
类程序
{
静态void Main(字符串[]参数)
{
var list=新列表();
IEnumerable对象=列表;
Func Func=s=>s.Contains(“x”);
列表。添加(“测试”);
列表。添加(“x”);
列表。添加(“mux”);
foreach(objects.Cast()中的var项,其中(d=>func(d)))
控制台写入线(项目);
Console.ReadKey();
}
}

您会遇到哪些异常/编译器错误?使用IEnumerable时,我会遇到:异常详细信息:System.ArgumentException:“TOId”在尝试执行左侧表达式和使用o时不是“System.Object”类型的成员。其中:“Object”不包含“Where”的定义接受“Object”类型的第一个参数可以找到(是否缺少指令或程序集引用?),但此错误消息为“正常”,在这种情况下,TOId是对象键的一部分…Where Extensions方法位于集合中,如果(o.Where(lineKey).Count()==0)//错误,则尝试将其称为对象类型!!!您会遇到哪些异常/编译器错误?当使用IEnumerable时,我得到了:异常详细信息:System.ArgumentException:“TOId”在尝试执行左表达式和使用o时不是“System.Object”类型的成员。其中:“Object”不包含“Where”的定义接受“Object”类型的第一个参数可能是找不到(是否缺少指令或程序集引用?),但如果TOId是对象键的一部分,则此错误消息为“正常”…Where Extensions方法位于集合中,如果(o.Where(lineKey).Count()==0)//错误,则尝试将其称为对象类型!!!不幸的是,对于这个问题,类型现在是一个HashSet,即使我重新定义where扩展方法来获取/检索HashSet;在运行时,我得到以下错误:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:'System.Collections.Generic.HashSet'不包含'Where'的定义。
不幸的是,由于这个问题,类型现在是一个HashSet,即使我重新定义了Where扩展方法来获取/检索HashSet;在运行时,我收到以下错误:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:“System.Collections.Generic.HashSet”不包含“Where”的定义。
谢谢您的回答。这就是我害怕的。。。我对扩展方法的主要兴趣是拥有一个干净的代码。。。如果我不得不称之为动态;那么使用它的优势(当然是在这种情况下)几乎为零……谢谢你的回答。这就是我害怕的。。。我对扩展方法的主要兴趣是拥有一个干净的代码。。。如果我不得不称之为动态;那么使用它的优势(当然是在这种情况下)几乎是零。。。
class Program
{
    static void Main(string[] args)
    {
        var list = new List<string>();
        IEnumerable<object> objects = list;
        Func<string, bool> func = s => s.Contains("x");

        list.Add("Test");
        list.Add("x");
        list.Add("mux");
        foreach (var item in objects.Cast<dynamic>().Where(d => func(d)))
            Console.WriteLine(item);
        Console.ReadKey();
    }
}