첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
728x90
반응형
728x170

▶ Type 클래스 : 자식 타입 여부 구하기 예제

/// <summary>
/// 테스트 인터페이스
/// </summary>
public interface ITest
{
}

/// <summary>
/// 테스트 제네릭 인터페이스
/// </summary>
/// <typeparam name="T"></typeparam>
public interface ITest<T>
{
}

/// <summary>
/// 테스트 베이스
/// </summary>
public class TestBase
{
}

/// <summary>
/// 테스트
/// </summary>
public class Test : TestBase, ITest
{
}

/// <summary>
/// 자식 테스트
/// </summary>
public class ChildTest : Test, ITest<object>
{
}

/// <summary>
/// 자식 테스트 제네릭
/// </summary>
/// <typeparam name="T"></typeparam>
public class ChildTest<T> : Test, ITest<T>
{
}

Console.WriteLine(IsChildType(typeof(Test), typeof(TestBase)));
Console.WriteLine(IsChildType(typeof(Test), typeof(ITest)));

Console.WriteLine();

Console.WriteLine(IsChildType(typeof(ChildTest), typeof(Test)));
Console.WriteLine(IsChildType(typeof(ChildTest), typeof(ITest<>)));
Console.WriteLine(IsChildType(typeof(ChildTest), typeof(TestBase)));
Console.WriteLine(IsChildType(typeof(ChildTest), typeof(ITest)));

Console.WriteLine();

Console.WriteLine(IsChildType(typeof(ChildTest<>), typeof(Test)));
Console.WriteLine(IsChildType(typeof(ChildTest<>), typeof(ITest<>)));
Console.WriteLine(IsChildType(typeof(ChildTest<>), typeof(TestBase)));
Console.WriteLine(IsChildType(typeof(ChildTest<>), typeof(ITest)));

 

728x90

 

▶ Type 클래스 : 자식 타입 여부 구하기

#region 자식 타입 여부 구하기 - IsChildType(childType, parentType)

/// <summary>
/// 자식 타입 여부 구하기
/// </summary>
/// <param name="childType">자식 타입</param>
/// <param name="parentType">부모 타입</param>
/// <returns>자식 타엽 여부</returns>
public bool IsChildType(Type childType, Type parentType)
{
    if(childType == parentType)
    {
        return false;
    }

    if(childType.IsSubclassOf(parentType))
    {
        return true;
    }

    Type[] genericArgumentTypeArray = parentType.GetGenericArguments();

    bool isParameterLessGeneric = !
    (
        genericArgumentTypeArray != null    &&
        genericArgumentTypeArray.Length > 0 &&
        ((genericArgumentTypeArray[0].Attributes & TypeAttributes.BeforeFieldInit) == TypeAttributes.BeforeFieldInit)
    );

    while(childType != null && childType != typeof(object))
    {
        Type fullType = GetFullTypeDefinition(childType);

        if
        (
            parentType == fullType ||
            (isParameterLessGeneric && fullType.GetInterfaces().Select(i => GetFullTypeDefinition(i)).Contains(GetFullTypeDefinition(parentType)))
        )
        {
            return true;
        }
        else if(!isParameterLessGeneric)
        {
            if(GetFullTypeDefinition(parentType) == fullType && !fullType.IsInterface)
            {
                if(VerifyGenericArguments(GetFullTypeDefinition(parentType), fullType))
                {
                    if(VerifyGenericArguments(parentType, childType))
                    {
                        return true;
                    }
                }
            }
            else
            {
                foreach(Type interfaceType in childType.GetInterfaces().Where(i => GetFullTypeDefinition(parentType) == GetFullTypeDefinition(i)))
                {
                    if(VerifyGenericArguments(parentType, interfaceType))
                    {
                        return true;
                    }
                }
            }
        }

        childType = childType.BaseType;
    }

    return false;
}

#endregion

#region 완전한 타입 정의 구하기 - GetFullTypeDefinition(sourceType)

/// <summary>
/// 완전한 타입 정의 구하기
/// </summary>
/// <param name="sourceType">소스 타입</param>
/// <returns>완전한 타입</returns>
private Type GetFullTypeDefinition(Type sourceType)
{
    return sourceType.IsGenericType ? sourceType.GetGenericTypeDefinition() : sourceType;
}

#endregion
#region 제네릭 인자 확인하기 - VerifyGenericArguments(parentType, childType)

/// <summary>
/// 제네릭 인자 확인하기
/// </summary>
/// <param name="parentType">부모 타입</param>
/// <param name="childType">자식 타입</param>
/// <returns>제네릭 인자 확인 결과</returns>
private bool VerifyGenericArguments(Type parentType, Type childType)
{
    Type[] childArgumentTypeArray  = childType.GetGenericArguments();
    Type[] parentArgumentTypeArray = parentType.GetGenericArguments();

    if(childArgumentTypeArray.Length == parentArgumentTypeArray.Length)
    {
        for(int i = 0; i < childArgumentTypeArray.Length; i++)
        {
            if
            (
                childArgumentTypeArray[i].Assembly  != parentArgumentTypeArray[i].Assembly ||
                childArgumentTypeArray[i].Name      != parentArgumentTypeArray[i].Name     ||
                childArgumentTypeArray[i].Namespace != parentArgumentTypeArray[i].Namespace
            )
            {
                if(!childArgumentTypeArray[i].IsSubclassOf(parentArgumentTypeArray[i]))
                {
                    return false;
                }
            }
        }
    }

    return true;
}

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

댓글을 달아 주세요