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

C# 如何使用反射来调节多个属性以检查LINQ.Where语句中的相等性,具体取决于传递的类?,c#,linq,reflection,C#,Linq,Reflection,我试图泛化一个重复的checker函数,它根据对象的类型,检查所述类(在配置中提供)的属性是否与另一个列表中的属性相同 我决定创建一个Dictionary,它将接受键(Book、Author、Shop等)的类型字符串和需要相等的属性数组 字典实体示例: "Book", ["Title", "CoverImage", "NumberOfPages"] "Author", ["Name", "Address", "SomethingElse"] 然后,我将一个对象传递给函数,并使用反射来获取类型

我试图泛化一个重复的checker函数,它根据对象的类型,检查所述类(在配置中提供)的属性是否与另一个列表中的属性相同

我决定创建一个Dictionary,它将接受键(Book、Author、Shop等)的类型字符串和需要相等的属性数组

字典实体示例:

"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
};
另外,因为
FirstOrDefault
还有重载,所以接受谓词最后一行可以重写为:

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

更好的解决方案是创建将标记属性的自定义属性。然后类内重写默认方法Equals,该方法将获取具有此属性的所有属性并返回相等值。

是否为linq to objects?
var first = someList.FirstOrDefault(x => configDictionary[typeName].All(f => f(x, obj)));