[c#] C #은 System.Type을 Generic 매개 변수로 사용합니다.

데이터베이스에서 쿼리해야하는 유형 (System.Type) 목록이 있습니다.

이 유형 각각에 대해 다음 확장 메서드 (LinqToNhibernate의 일부)를 호출해야합니다.

Session.Linq<MyType>()

그러나 MyType이 없지만 대신 Type을 사용하고 싶습니다.

내가 가진 것은 :

System.Type typeOne;

그러나 다음을 수행 할 수 없습니다.

Session.Linq<typeOne>()

유형을 일반 매개 변수로 어떻게 사용할 수 있습니까?



답변

직접 할 수는 없습니다. 제네릭의 요점은 컴파일 타임에 관심있는 유형을 알고 해당 유형의 인스턴스로 작업 할 수있는 컴파일 타임 유형 안전성 을 제공 하는 것입니다. 귀하의 경우에는을 알고 Type있으므로 보유한 객체가 해당 유형의 인스턴스라는 컴파일 시간 검사를 얻을 수 없습니다.

다음과 같이 리플렉션을 통해 메서드를 호출해야합니다.

// Get the generic type definition
MethodInfo method = typeof(Session).GetMethod("Linq",
                                BindingFlags.Public | BindingFlags.Static);

// Build a method with the specific type argument you're interested in
method = method.MakeGenericMethod(typeOne);
// The "null" is because it's a static method
method.Invoke(null, arguments);

이 유형을 많이 사용해야하는 경우 필요한 다른 제네릭 메서드를 호출하는 고유 한 제네릭 메서드를 작성한 다음 리플렉션을 사용 하여 메서드 를 호출하는 것이 더 편리 할 수 ​​있습니다 .


답변

이렇게하려면 리플렉션을 사용해야합니다.

typeof(Session).GetMethod("Linq").MakeGenericMethod(typeOne).Invoke(null, null);

( Linq<T>()유형에 대한 정적 메서드 라고 가정 Session)

경우 Session실제로 객체가 , 당신은 어디에서 알아야 할 Linq방법이 실제로 선언과에 합격 Session인수로 :

typeof(DeclaringType).GetMethod("Linq").MakeGenericMethod(typeOne)
     .Invoke(null, new object[] {Session});


답변

반사를 통해 일반 메서드 호출을 호출하는 일반적인 메서드가 하나 있습니다.

/// <summary>
    /// This method call your method through Reflection 
    /// so i wil call the method like CallGenericMethodThroughReflection<Session>(assemblyQualifiedName,Linq,false,new[] { file }) 
    /// </summary>
    /// <typeparam name="T">Call method from which file</typeparam>
    /// <param name="assemblyQualifiedName">Your can get assemblyQualifiedName like typeof(Payroll.Domain.Attendance.AttendanceApplicationMaster).AssemblyQualifiedName</param>
    /// <param name="methodName"></param>
    /// <param name="isStaticMethod"></param>
    /// <param name="paramaterList"></param>
    /// <param name="parameterType">pass parameter type list in case of the given method have overload  </param>
    /// <returns>return object of calling method</returns>
    public static object CallGenericMethodThroughReflection<T>(string assemblyQualifiedName, string methodName,bool isStaticMethod ,object[] paramaterList,Type[] parameterType = null)
    {
        try
        {
            object instance = null;
            var bindingAttr = BindingFlags.Static | BindingFlags.Public;
            if (!isStaticMethod)
            {
                instance = Activator.CreateInstance<T>();
                bindingAttr = BindingFlags.Instance | BindingFlags.Public;
            }
            MethodInfo MI = null;
            var type = Type.GetType(assemblyQualifiedName);
            if(parameterType == null)
                MI = typeof(T).GetMethod(methodName, bindingAttr);
            else
                MI = typeof(T).GetMethod(methodName, bindingAttr,null, parameterType, null);//this will work in most case some case not work
            if (type == null || MI == null) // if the condition is true it means given method or AssemblyQualifiedName entity not found
                return null;
            var genericMethod = MI.MakeGenericMethod(new[] { type });
            return genericMethod.Invoke(instance, paramaterList);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }


답변