첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
728x90
반응형
728x170
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;

#region 객체 컬렉션 특정 객체 속성 값의 집합 구하기 - GetDistinctCollection(sourceCollection, propertyNameArray)

/// <summary>
/// 객체 컬렉션 특정 객체 속성 값의 집합 구하기
/// </summary>
/// <param name="sourceCollection">소스 컬렉션</param>
/// <param name="propertyNameArray">속성명 배열</param>
/// <returns>객체 컬렉션 특정 객체 속성 값의 집합</returns>
public ObservableCollection<object> GetDistinctCollection(ObservableCollection<object> sourceCollection, string[] propertyNameArray)
{
    if(sourceCollection == null || sourceCollection.Count == 0)
    {
        return null;
    }

    var result = sourceCollection.AsEnumerable().GroupBy(item => new DistinctTuple<object>(from propertyName in propertyNameArray select item.GetType().GetProperty(propertyName).GetValue(item)));

    int propertyNameCount = propertyNameArray.Length;

    PropertyDescriptorCollection pdc = TypeDescriptor.GetProperties(sourceCollection[0]);

    DynamicClass dynamicClass = new DynamicClass(); // '동적 클래스 사용하기' 참조

    for(int i = 0; i < propertyNameCount; i++)
    {
        dynamicClass.AddProperty(propertyNameArray[i], pdc[propertyNameArray[i]].PropertyType);
    }

    dynamicClass.CreateType();

    ObservableCollection<object> targetCollection = new ObservableCollection<object>();

    foreach(var group in result)
    {
        dynamicClass.CreateInstance();

        for(int i = 0; i < propertyNameCount; i++)
        {
            dynamicClass.SetValue(i, group.Key.ValueArray[i]);
        }

        targetCollection.Add(dynamicClass.Instance);
    }

    return targetCollection;
}

#endregion



/// <summary>
/// 중복 제거 튜플
/// </summary>
/// <typeparam name="T">타입</typeparam>
public class DistinctTuple<T> : IEquatable<DistinctTuple<T>>
{
    //////////////////////////////////////////////////////////////////////////////////////////////////// Field
    ////////////////////////////////////////////////////////////////////////////////////////// Public

    #region Field

    /// <summary>
    /// 값 배열
    /// </summary>
    public readonly T[] ValueArray;

    #endregion

    //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
    ////////////////////////////////////////////////////////////////////////////////////////// Public

    #region 생성자 - DistinctTuple(enumerable)

    /// <summary>
    /// 생성자
    /// </summary>
    /// <param name="enumerable">열거 가능형</param>
    public DistinctTuple(IEnumerable<T> enumerable)
    {
        ValueArray = enumerable.ToArray();
    }

    #endregion

    //////////////////////////////////////////////////////////////////////////////////////////////////// Method
    ////////////////////////////////////////////////////////////////////////////////////////// Public

    #region 동등 여부 조사하기 - Equals(sourceTuple)

    /// <summary>
    /// 동등 여부 조사하기
    /// </summary>
    /// <param name="sourceTuple">소스 Tuple</param>
    /// <returns>동등 여부</returns>
    public bool Equals(DistinctTuple<T> sourceTuple)
    {
        if(ReferenceEquals(this, sourceTuple))
        {
            return true;
        }

        if(sourceTuple == null)
        {
            return false;
        }

        int length = ValueArray.Length;

        if(length != sourceTuple.ValueArray.Length)
        {
            return false;
        }

        for(int i = 0; i < length; i++)
        {
            if(!Equals(ValueArray[i], sourceTuple.ValueArray[i]))
            {
                return false;
            }
        }

        return true;
    }

    #endregion

    #region 동등 여부 조사하기 - Equals(sourceObject)

    /// <summary>
    /// 동등 여부 조사하기
    /// </summary>
    /// <param name="sourceObject">소스 객체</param>
    /// <returns>동등 여부</returns>
    public override bool Equals(object sourceObject)
    {
        if(ReferenceEquals(this, sourceObject))
        {
            return false;
        }

        if(sourceObject == null)
        {
            return false;
        }

        return Equals(sourceObject as DistinctTuple<T>);
    }

    #endregion

    #region 해시 코드 구하기 - GetHashCode()

    /// <summary>
    /// 해시 코드 구하기
    /// </summary>
    /// <returns>해시 코드</returns>
    public override int GetHashCode()
    {
        int hashCode = 17;

        foreach(var value in ValueArray)
        {
            hashCode = hashCode * 37 + (!ReferenceEquals(value, null) ? value.GetHashCode() : 0);
        }

        return hashCode;
    }

    #endregion
}
728x90
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요