2011년 10월 11일 화요일

HashCode 제작 Tool

HashCode를 계산하는 메소드를 제공하는 HashTool 클래스입니다.
NHibernate 등 DDD 패턴에서 고유한 HashCode 값 생성이 상당히 중요합니다. 이를 위해 제작한 클래스이고, 현재까지 잘 작동하는 코드입니다.^^

using System;
using System.Linq;
using System.Linq.Expressions;
using RCL.LinqExtensions;

namespace RCL.Core
{
	/// 
	/// HashCode 를 생성해주는 Tool Class 입니다.
	/// 
	public static class HashTool
	{
		private const int Factor = 31;
		private const int InitValue = 1;
		public const int NullValue = 0;

		private static readonly int EmptyStringHashCode = string.Empty.GetHashCode();

		/// 
		/// 지정된 객체들의 HashCode를 계산합니다.
		/// 
		public static int Compute(object obj)
		{
			return (obj != null) ? obj.GetHashCode() : NullValue;
		}

		/// 
		/// 지정된 객체들의 HashCode를 계산합니다.
		/// 
		public static int Compute(object obj1, object obj2)
		{
			return Compute(obj1) * Factor + Compute(obj2);
		}

		/// 
		/// 지정된 객체들의 HashCode를 계산합니다.
		/// 
		public static int Compute(object obj1, object obj2, object obj3)
		{
			return Compute(obj1, obj2) * Factor + Compute(obj3);
		}

		/// 
		/// 지정된 객체들의 HashCode를 계산합니다.
		/// 
		public static int Compute(object obj1, object obj2, object obj3, object obj4)
		{
			return Compute(obj1, obj2, obj3) * Factor + Compute(obj4);
		}

		/// 
		/// 지정된 객체들의 HashCode를 계산합니다.
		/// 
		/// 객체를 입력하세요 (GetHashCode를 넣지 마세요)
		/// 
		public static int Compute(params object[] objs)
		{
			int hash = NullValue;

			if(objs != null)
				foreach(var obj in objs)
					hash = hash * Factor + Compute(obj);

			return hash;
		}

		/// 
		/// 문자열의 HashCode를 반환합니다. null 이거나 빈문자열이면 string.Empty.GetHashCode() 값을 반환합니다. (0은 아닙니다)
		/// 
		/// 
		/// 
		public static int CalcHash(this string str)
		{
			return str.IsEmpty() ? EmptyStringHashCode : str.GetHashCode();
		}

		/// 
		/// 인스턴스의 특정 속성들로부터 HashCode를 생성합니다.
		/// 
		/// 대상 객체의 수형
		/// 해시코드를 얻고자하는 대상 객체
		/// 해시코드 조합용 속성들
		/// 
		public static int CalcHash(this T target, params Expression>[] propertyExprs)
		{
			if(Equals(target, default(T)))
				return 0;

#if !SILVERLIGHT

			if(propertyExprs == null || propertyExprs.Length == 0)
				return target.GetHashCode();

			var propertyNames = propertyExprs.Select(expr => expr.Body.FindMemberName()).ToArray();
			var accessor = DynamicAccessorFactory.CreateDynamicAccessor(MapPropertyOptions.Safety);

			return Compute(propertyNames.Select(name => accessor.GetPropertyValue(target, name)).ToArray());
#else
			return target.GetHashCode();
#endif
		}
	}
}

HTML 코드에서 글을 써야 해서 좀 문제가 있네요^^

댓글 없음: