c# - 如何使用反射来调节多个属性以检查 LINQ .Where 语句中的相等性,具体取决于传递的类?

标签 c# linq reflection

我试图概括一个重复检查器函数,该函数根据对象的类型,检查所述类具有的属性(在配置中提供)是否等于另一个列表中的属性。

我决定创建一个字典,它将接受键的类型字符串(书籍、作者、商店等)以及需要相等的属性数组。

字典实体示例:

"Book", ["Title", "CoverImage", "NumberOfPages"] 
"Author", ["Name", "Address", "SomethingElse"]

然后,我将一个对象传递给函数并使用反射来获取类型的名称...

obj.GetType().Name;

...然后我用它从字典中获取正确的 KVP,这意味着如果我传递 Book 对象,我会得到“Book”。然后我们使用它来通过...获取配置

configDictionary["obj.GetType().Name"]

...它为我们提供了字符串数组,这些字符串是我们需要检查相等性的属性。

我已经到了需要类似内容的部分

list.Where(x => --> for each of the strings in the array - x.GetType.GetProperty(string) && --> same for next string && same for next string

...然后我需要用...来结束它

x.Id != obj.Id

为了确保我们根据逻辑检查重复项(不同的 ID 并匹配所有属性,但具有不同的 ID,因此 - 重复项)。

最终查询应该如下所示

书籍:

someList.Where(x => 
x.Title == obj.Title 
&& x.CoverImage == obj.CoverImage 
&& x.NumberOfPages == obj.NumberOfPages 
&& x.Id != obj.Id)
.FirstOrDefault();

作者:

someList.Where(x => x.Name == obj.Name 
&& x.Address == obj.Address 
&& x.SomethingElse == obj.SomethingElse 
&& x.Id != obj.Id)FirstOrDefault();

最佳答案

尽量避免反射,因为它会减慢应用程序的速度。作为替代方案,您可以创建一个字典并将所有比较器放入其中:

var configDictionary = new Dictionary<string, List<Func<object, object, bool>>>
{
    {
        "Book",
        new List<Func<object, object, bool>>
        {
            (b1, b2) => ((Book)b1).Title == ((Book)b2).Title,
            (b1, b2) => ((Book)b1).CoverImage == ((Book)b2).CoverImage,
            (b1, b2) => ((Book)b1).NumberOfPages == ((Book)b2).NumberOfPages,
            (b1, b2) => ((Book)b1).Id != ((Book)b2).Id,
        }
    },
    // same for Authors
};

现在您可以在 Where 方法中使用它:

var typeName = obj.GetType().Name; // here we using Reflection but once per collection, not per each item
var first = someList.Where(x => configDictionary[typeName].All(f => f(x, obj))).FirstOrDefault();

此外,由于 FirstOrDefault 也具有重载,因此接受谓词最后一行可以重写为:

var first = someList.FirstOrDefault(x => configDictionary[typeName].All(f => f(x, obj)));

关于c# - 如何使用反射来调节多个属性以检查 LINQ .Where 语句中的相等性,具体取决于传递的类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56936075/

相关文章:

c# - 如何使用 C# 从 FTP 服务器获取一系列文件

reflection - 如何获取实现接口(interface)的 Go 包中定义的所有类型?

c# - 如何在复杂的脚本中获取上下文形状输入的字符?

c# - 列出内部 IQueryable 对象

linq - 如何使用 LINQ 对对象列表执行函数

c# - 使用 linq 获取逗号分隔的实体集合列表

java - 我如何使用java中的反射访问内部类变量值?

c# - 通过反射获取基类的私有(private)属性/方法

c# - 是否存在用于生成 WCF 服务以为 self 跟踪实体提供获取和保存的 T4 模板?

c# - EF Generic Repository 从新插入的通用实体获取 Id