c# - 如何使用反射来调节多个属性以检查 LINQ .Where 语句中的相等性,具体取决于传递的类?
问题描述
我正在尝试概括一个重复检查器功能,该功能取决于对象的类型,检查所述类具有的属性(在配置中提供)是否等于另一个列表中的属性。
我决定创建一个字典,它将接受键的类型字符串(书籍、作者、商店等)和需要相等的属性数组。
字典实体示例:
"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)));
推荐阅读
- arrays - 特定列中的唯一值仅二维数组(使用 numpy)
- ios - 是否建议在完成与它们的工作后销毁 UIViewController
- c# - 根据实体名称和属性名称返回属性的数据类型
- c - 需要帮助弄清楚为什么我的一个测试用例没有通过
- c# - 如何在 svn 中使用 NuGet 包?
- tensorflow-datasets - 从多个 TFRecord 文件中读取
- python - 请求 html。AttributeError: __aexit__ error with asyncio 如何解决?
- excel - 从表中创建动态列表 [Excel 365]
- node.js - 在角度节点multer中上传多个文件
- raspberry-pi - 如何在 Nerves 中设置 wlan0