Return 检查匹配属性的 C# 对象列表中的单个对象
Return a single object from a list of C# objects checking for matching properties
我需要创建一个对象 'factory',其工作方式如下:
- 接受匹配对象类型的列表。
- 比较列表中的每个 属性 值以查看它们是否匹配。
- Returns 该对象类型的新单个实例,仅设置了匹配字段。
(为简单起见,我们假设所有属性都是字符串)
例如,从这个人物对象列表中:
Person1 { Name: "Bob", Job: "Policeman", Location: "London" }
Person2 { Name: "John", Job: "Dentist", Location: "Florida" }
Person3 { Name: "Mike", Job: "Dentist", Location: "London" }
Person4 { Name: "Fred", Job: "Doctor", Location: "London" }
如果我传入一个包含第 2 个人和第 3 个人的列表,它将 return 一个像这样的新人:
Name: "No Match", Job: "Dentist", Location "No Match"
如果我通过第 3 和第 4 个人,它将 return 一个新人:
Name: "No Match", Job: "No Match", Location "London"
到目前为止....
使用这个 SO 问题的答案
:
How to check if all list items have the same value and return it, or return an “otherValue” if they don’t?
我可以让这个 LINQ 为单个已知对象工作,但我需要它是通用的。
这仅涵盖一个特定的 属性,但我的对象有 30 多个属性。
var otherValue="No Match"
var matchingVal= people.First().Job;
return people.All(x=>x.Job== matchingVal) ? matchingVal: otherValue;
我也知道我可以使用反射来获取对象中的属性列表。但是如何将所有这些组合成一个 'factory' 是无法理解的。
我不认为这是一个独特的问题,但我在任何搜索中都找不到完整的解决方案。也许那里已经有一个 Nuget 包可以帮助我?
感谢收到所有建议。
您的输入是某种特定类型对象的枚举,您必须创建一个相同类型的对象,其中填充了所有属性,所有值都相同。这可以通过这样的方式完成:
private static T GetCommonProperties<T>(IEnumerable<T> source) where T : new()
{
var first = true;
var common = new T();
var props = typeof(T).GetProperties();
foreach (var item in source)
{
if (first)
{
first = false;
foreach (var prop in props)
{
var value = prop.GetValue(item, null);
prop.SetValue(common, value);
}
}
else
{
foreach (var prop in props)
{
var itemValue = prop.GetValue(item, null);
var commonValue = prop.GetValue(common, null);
if ((dynamic)itemValue != (dynamic)commonValue)
{
prop.SetValue(common, GetDefault(prop.PropertyType));
}
}
}
}
return common;
}
给定的方法并不是真正最优的,因为它使用 dynamic
技巧来解决装箱值的比较问题。同样获取特定类型的默认值也可以通过这种通用方法实现:
private static object GetDefault(Type t)
{
return typeof(Program)
.GetMethod(nameof(GetDefaultValue), BindingFlags.NonPublic | BindingFlags.Static)
.MakeGenericMethod(t)
.Invoke(null, null);
}
private static T GetDefaultValue<T>()
{
return default;
}
但也可以提供 switch 语句或 Dictionary<Type, object>
如果没有可用的匹配项,returns 所需的默认值。
最后但同样重要的是,另一个可能的性能改进是从 props
变量中删除所有 PropertyInfo
条目,因为对于任何下一个即将到来的对象,此检查不再需要并且相同方式,当没有更多的道具可用时,循环可以提前退出。
可以找到一个工作示例 here。
我需要创建一个对象 'factory',其工作方式如下:
- 接受匹配对象类型的列表。
- 比较列表中的每个 属性 值以查看它们是否匹配。
- Returns 该对象类型的新单个实例,仅设置了匹配字段。
(为简单起见,我们假设所有属性都是字符串)
例如,从这个人物对象列表中:
Person1 { Name: "Bob", Job: "Policeman", Location: "London" }
Person2 { Name: "John", Job: "Dentist", Location: "Florida" }
Person3 { Name: "Mike", Job: "Dentist", Location: "London" }
Person4 { Name: "Fred", Job: "Doctor", Location: "London" }
如果我传入一个包含第 2 个人和第 3 个人的列表,它将 return 一个像这样的新人:
Name: "No Match", Job: "Dentist", Location "No Match"
如果我通过第 3 和第 4 个人,它将 return 一个新人:
Name: "No Match", Job: "No Match", Location "London"
到目前为止....
使用这个 SO 问题的答案
:
How to check if all list items have the same value and return it, or return an “otherValue” if they don’t?
我可以让这个 LINQ 为单个已知对象工作,但我需要它是通用的。
这仅涵盖一个特定的 属性,但我的对象有 30 多个属性。
var otherValue="No Match"
var matchingVal= people.First().Job;
return people.All(x=>x.Job== matchingVal) ? matchingVal: otherValue;
我也知道我可以使用反射来获取对象中的属性列表。但是如何将所有这些组合成一个 'factory' 是无法理解的。
我不认为这是一个独特的问题,但我在任何搜索中都找不到完整的解决方案。也许那里已经有一个 Nuget 包可以帮助我?
感谢收到所有建议。
您的输入是某种特定类型对象的枚举,您必须创建一个相同类型的对象,其中填充了所有属性,所有值都相同。这可以通过这样的方式完成:
private static T GetCommonProperties<T>(IEnumerable<T> source) where T : new()
{
var first = true;
var common = new T();
var props = typeof(T).GetProperties();
foreach (var item in source)
{
if (first)
{
first = false;
foreach (var prop in props)
{
var value = prop.GetValue(item, null);
prop.SetValue(common, value);
}
}
else
{
foreach (var prop in props)
{
var itemValue = prop.GetValue(item, null);
var commonValue = prop.GetValue(common, null);
if ((dynamic)itemValue != (dynamic)commonValue)
{
prop.SetValue(common, GetDefault(prop.PropertyType));
}
}
}
}
return common;
}
给定的方法并不是真正最优的,因为它使用 dynamic
技巧来解决装箱值的比较问题。同样获取特定类型的默认值也可以通过这种通用方法实现:
private static object GetDefault(Type t)
{
return typeof(Program)
.GetMethod(nameof(GetDefaultValue), BindingFlags.NonPublic | BindingFlags.Static)
.MakeGenericMethod(t)
.Invoke(null, null);
}
private static T GetDefaultValue<T>()
{
return default;
}
但也可以提供 switch 语句或 Dictionary<Type, object>
如果没有可用的匹配项,returns 所需的默认值。
最后但同样重要的是,另一个可能的性能改进是从 props
变量中删除所有 PropertyInfo
条目,因为对于任何下一个即将到来的对象,此检查不再需要并且相同方式,当没有更多的道具可用时,循环可以提前退出。
可以找到一个工作示例 here。