using System;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace TestProject
{
/// <summary>
/// 타입 헬퍼
/// </summary>
public static class TypeHelper
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 캐스트 캐시 딕셔너리
/// </summary>
private static readonly Dictionary<Tuple<Type, Type>, Func<object, object>> _castCacheDictionary = new Dictionary<Tuple<Type, Type>, Func<object, object>>();
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Public
#region 타입 변경하기 - ChangeType(sourceObject)
/// <summary>
/// 타입 변경하기
/// </summary>
/// <typeparam name="TTarget">타겟 타입</typeparam>
/// <param name="sourceObject">소스 객체</param>
/// <returns>타입 변경 객체</returns>
public static TTarget ChangeType<TTarget>(object sourceObject)
{
return (TTarget)GetCastFunction(sourceObject.GetType(), typeof(TTarget)).Invoke(sourceObject);
}
#endregion
//////////////////////////////////////////////////////////////////////////////// Private
#region 캐스트 함수 생성하기 - CreateCastFunction(sourceType, targetType)
/// <summary>
/// 캐스트 함수 생성하기
/// </summary>
/// <param name="sourceType">소스 타입</param>
/// <param name="targetType">타겟 타입</param>
/// <returns>캐스트 함수</returns>
private static Func<object, object> CreateCastFunction(Type sourceType, Type targetType)
{
ParameterExpression parameterExpression = Expression.Parameter(typeof(object));
return Expression.Lambda<Func<object, object>>
(
Expression.Convert
(
Expression.ConvertChecked(Expression.Convert(parameterExpression, sourceType), targetType),
typeof(object)
),
parameterExpression
).Compile();
}
#endregion
#region 캐스트 함수 구하기 - GetCastFunction(sourceType, targetType)
/// <summary>
/// 캐스트 함수 구하기
/// </summary>
/// <param name="sourceType">소스 타겟</param>
/// <param name="targetType">타겟 타입</param>
/// <returns>캐스트 함수</returns>
private static Func<object, object> GetCastFunction(Type sourceType, Type targetType)
{
lock(_castCacheDictionary)
{
Tuple<Type, Type> keyTuple = new Tuple<Type, Type>(sourceType, targetType);
Func<object, object> castFunction;
if(!_castCacheDictionary.TryGetValue(keyTuple, out castFunction))
{
castFunction = CreateCastFunction(sourceType, targetType);
_castCacheDictionary.Add(keyTuple, castFunction);
}
return castFunction;
}
}
#endregion
}
}