3

ある時点ですべてのメトリックにアクセスできるようにする必要があるため、一連のデータ クラスを整理する最善の方法を見つけようとしています。

これが私の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 がすべてのプロパティの値を持つわけではありません。値が設定された 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 の 2 つのコレクションを構築し、それらを並べて比較して違いを確認しているためです (それらは同一である必要があります)。最初にこのより高いレベルでメトリックを比較し、次に正確に異なる部分を分析できるようにしたいと考えています。

これを達成する方法に光を当ててくれてありがとう。:-)

4

3 に答える 3

2

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();
        }
    }
}
于 2013-09-16T08:32:23.550 に答える
1

次の linq クエリを使用して、タイトル数を取得できます。

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

次のように、クローズの数を取得できます。

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

より大きなコレクションを作成する場合、または値に頻繁にアクセスする場合は、フィールド カウントを格納するカスタム コレクションの実装を作成する価値があるかもしれません。項目を追加および削除すると、これらの値を増減できます。項目を追加および削除すると更新されるこのカスタム コレクションに、ステータス カウントのディクショナリを格納することもできます。

于 2013-09-16T07:55:00.180 に答える