繁体   English   中英

C#中包含自定义集合的元素度量标准

[英]Element Metrics with Custom collection in C#

我试图找出组织我的数据类的最佳方法,因为我需要能够在某些时候访问它们的所有指标。

这是我的OR类的片段:

public enum status { CLOSED, OPEN }

public class OR
{
    public string reference { get; set; }
    public string title { get; set; }
    public status status { get; set; }
}

并非每个OR I初始化都具有所有属性的值。 我希望能够以这样的方式“收集”成千上万的这些,以便我可以轻松获得有多少OR对象具有值集的计数。 例如:

OR a = new OR() { reference = "a" }
OR b = new OR() { reference = "b", title = "test" }
OR c = new OR() { reference = "c", title = "test", status = status.CLOSED }

现在这些以某种方式收集我可以做(伪):

int titleCount = ORCollection.titleCount;
titleCount = 2

我还希望能够收集枚举类型属性的度量标准,例如从集合中检索一个类似于以下内容的Dictionary

Dictionary<string, int> statusCounts = { "CLOSED", 1 }

想要访问这些指标的原因是我正在构建两个OR集合,并将它们并排比较任何差异(它们应该是相同的)。 我希望能够首先在这个更高级别比较他们的指标,然后在精确区别的地方进行细分。

感谢任何可以解决如何实现这一目标的光。 :-)

......'收集'成千上万的这些

成千上万不是一个庞大的数字。 只需使用List<OR> ,您就可以使用Linq查询获取所有指标。

例如:

List<OR> orList = ...;

int titleCount = orList
       .Where(o => ! string.IsNullOrEmpty(o.title))
       .Count(); 

Dictionary<status, int> statusCounts = orList
        .GroupBy(o => o.status)
        .ToDictionary(g => g.Key, g => g.Count());

使用Linq的现有答案非常棒,非常优雅,所以下面提出的想法仅适用于后代。

这是一个(非常粗略的)基于反射的程序,它将使您计算任何对象集合中的“有效”属性。

您在Validators字典中定义了验证器,以便您可以轻松更改每个属性的有效/无效值。 如果您最终得到具有大量属性的对象并且不希望必须在每个属性的实际集合本身上编写内联linq指标,那么您可能会发现它很有用。

您可以将其作为一个函数武器化,然后针对两个集合运行它,为您提供报告两者之间确切差异的基础,因为它记录了对最终字典中各个对象的引用。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;

namespace reftest1
{
    public enum status { CLOSED, OPEN }

    public class OR 
    {
        public string reference { get; set; }
        public string title { get; set; }
        public status status { get; set; }
        public int foo { get; set; }

    }

    //creates a dictionary by property of objects whereby that property is a valid value
    class Program
    {

        //create dictionary containing what constitues an invalid value here
        static Dictionary<string,Func<object,bool>> Validators = new Dictionary<string, Func<object,bool>>
            {

                {"reference", 
                    (r)=> { if (r ==null) return false;
                              return !String.IsNullOrEmpty(r.ToString());}
                },
                {"title",
                    (t)=> { if (t ==null) return false;
                              return !String.IsNullOrEmpty(t.ToString());}
               }, 
               {"status", (s) =>
                    {
                        if (s == null) return false;
                        return !String.IsNullOrEmpty(s.ToString());
              }},
             {"foo",
                 (f) =>{if (f == null) return false;
                            return !(Convert.ToInt32(f.ToString()) == 0);}
                    }
            };

        static void Main(string[] args)
        {
            var collection = new List<OR>();
            collection.Add(new OR() {reference = "a",foo=1,});
            collection.Add(new OR(){reference = "b", title = "test"});
            collection.Add(new OR(){reference = "c", title = "test", status = status.CLOSED});

            Type T = typeof (OR);
            var PropertyMetrics = new Dictionary<string, List<OR>>();
            foreach (var pi in GetProperties(T))
            {
                PropertyMetrics.Add(pi.Name,new List<OR>());
                foreach (var item in collection)
                {
                    //execute validator if defined
                    if (Validators.ContainsKey(pi.Name))
                    {
                       //get actual property value and compare to valid value
                       var value = pi.GetValue(item, null);
                       //if the value is valid, record the object into the dictionary
                       if (Validators[pi.Name](value))
                       {
                           var lookup = PropertyMetrics[pi.Name];
                           lookup.Add(item);
                       }
                    }//end trygetvalue
                }
            }//end foreach pi
            foreach (var metric in PropertyMetrics)
            {
                Console.WriteLine("Property '{0}' is set in {1} objects in collection",metric.Key,metric.Value.Count);
            }
            Console.ReadLine();
        }


        private static List<PropertyInfo> GetProperties(Type T)
        {
            return T.GetProperties(BindingFlags.Public | BindingFlags.Instance).ToList();
        }
    }
}

您可以使用此linq查询获取标题计数:

int titleCount = ORCollection
                    .Where(x => !string.IsNullOrWhiteSpace(x.title))
                    .Count();

你可以像这样得到关闭的数量:

int closedCount = ORCollection
                     .Where(x => x.status == status.CLOSED)
                     .Count();

如果您要拥有更大的集合,或者您可以大量访问这些值,那么可能需要创建一个存储字段计数的自定义集合实现,然后可以在添加和删除项目时递增/递减这些值。 您还可以在此自定义集合中存储状态计数字典,并在添加和删除项目时进行更新。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM