从检查匹配属性的 C# 对象列表中返回单个对象

发布于 2025-01-14 11:53:32 字数 1235 浏览 3 评论 0原文

我需要创建一个对象“工厂”,其工作原理如下:

  1. 接受匹配对象类型的列表。
  2. 比较列表中的每个属性值以查看它们是否匹配。
  3. 返回该对象类型的新的单个实例,仅设置匹配的字段。

(为了简单起见,我们可以假设所有属性都是字符串)

例如,从这个 person 对象列表中:

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"   }

如果我传入一个包含 person 2 & 的列表。 3 它将返回一个新的人,如下所示:

Name: "No Match", Job: "Dentist", Location "No Match"

如果我通过了人 3 & 4 它将返回一个新人:

Name: "No Match", Job: "No Match", Location "London"

到目前为止....
使用这个问题的答案 :
如何检查所有列表项是否具有相同的值并返回它,或者如果不同则返回“otherValue”?

我可以让这个 LINQ 适用于单个已知对象,但我需要它是通用的。
这仅涵盖一个特定属性,但我的对象有 30 多个属性。

var otherValue="No Match"
var matchingVal= people.First().Job;
return people.All(x=>x.Job== matchingVal) ? matchingVal: otherValue; 

我还知道我可以使用反射来获取对象中的属性列表。但如何将所有这些组合到一个“工厂”中却是难以理解的。

我不认为这是一个独特的问题,但我在任何搜索中都找不到完整的解决方案。也许已经有一个 Nuget 包可以帮助我?

非常感谢所有建议。

I have a requirement to create an object 'factory' that works as follows:

  1. Accepts a list of matching object types.
  2. Compares each property value in the list to see if they match.
  3. Returns a new single instance of that object type, with just the matching fields set.

(For simplicity, we can assume all propeties are strings)

For example, from this list of person objects:

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"   }

If I passed in a list containing person 2 & 3 it would return a new person like so:

Name: "No Match", Job: "Dentist", Location "No Match"

If I passed in person 3 & 4 it would return a new person:

Name: "No Match", Job: "No Match", Location "London"

So far....
Using the answer from this SO question
:
How to check if all list items have the same value and return it, or return an “otherValue” if they don’t?

I can get this LINQ to work for a single known object, but I need it to be generic.
This covers just one specific property but my objects have 30+ properties.

var otherValue="No Match"
var matchingVal= people.First().Job;
return people.All(x=>x.Job== matchingVal) ? matchingVal: otherValue; 

I am also aware I can use reflection to get a list of properties in my object. But how to combine all of that into a single 'factory' is beyond by comprehension.

I don't think this is a unique problem but I cannot find a complete solution in any of my searching. Maybe there is already a Nuget package out there that can help me?

All advice gratefully received.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

瀟灑尐姊 2025-01-21 11:53:32

您的输入是某种特定类型对象的枚举,您必须创建一个相同类型的对象,其中所有属性都已填充,并且所有值都相同。这可以通过这样的方法来完成:

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 来返回所需的默认值(如果没有)匹配可用。

最后但并非最不重要的一点是,另一个可能的性能改进是从 props 变量中删除所有 PropertyInfo 条目,因为对于任何下一个即将到来的对象,不再需要此检查,并且同样,当不再有可用的道具时,可以提前退出循环。

可以在此处找到一个有效的示例。

Your input is an enumeration of some specific kind of objects and you have to create an object of the same type where all properties are filled, where all values are the same. This could be done with something like this:

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;
}

The given method is not really optimal, cause it uses the dynamic trick to solve the comparison problem of boxed values. Also getting the default value for a specific type could probably implemented by this generic approach:

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;
}

But it would also be possible to provide a switch statement or Dictionary<Type, object> that returns the desired default value if no match available.

Last but not least, another possible performance improvement would be to remove all PropertyInfo entries from the props variable, cause for any next upcoming object, this check is not necessary anymore and the same way, the loop could be early exited, when no more props are available anymore.

A working example can be found here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文