参考微软说明: How to: Examine and Instantiate Generic Types with Reflection - .NET Framework | Microsoft Learn
目标方法
public class GenericTest{public Dictionary<string, string> TestGeneric<T1, T2>(T1 t1, T2 t2)where T1 : TestBase, ITestArgument where T2 : class, new(){return null;}}
//判断逻辑
var testType = typeof(GenericTest);
var methods = testType.GetMethods();//获取泛型方法
var genericMethod = methods[0];
//判断是否是泛型
if (!genericMethod.IsGenericMethod)
{return;
}
//获取泛型信息<T1, T2>
var genericArgs = genericMethod.GetGenericArguments();
//获取泛型T1
var arg1 = genericArgs[0];
//获取T1名称
var name = arg1.Name;
//获取约束 T1约束, where T1: TestBase, ITestArgument
var arg1constraints = arg1.GetGenericParameterConstraints();
foreach (Type iConstraint in arg1constraints)
{if (iConstraint.IsInterface){//ITestArgumentvar itestArgumentName = iConstraint.Name;}else{//TestBasevar testBaseName = iConstraint.Name;}
}
//获取T2约束 where T2 : class, new()
var arg2 = genericArgs[1];
GenericParameterAttributes arg2Constraints =arg2.GenericParameterAttributes &GenericParameterAttributes.SpecialConstraintMask;if (arg2Constraints != GenericParameterAttributes.None)
{if (GenericParameterAttributes.None != (arg2Constraints &GenericParameterAttributes.DefaultConstructorConstraint)){//包含 new()}if (GenericParameterAttributes.None != (arg2Constraints &GenericParameterAttributes.ReferenceTypeConstraint)){//包含 class}if (GenericParameterAttributes.None != (arg2Constraints &GenericParameterAttributes.NotNullableValueTypeConstraint)){//包含 notnull}
}
官网示例代码
using System;
using System.Reflection;
using System.Collections.Generic;// Define an example interface.
public interface ITestArgument {}// Define an example base class.
public class TestBase {}// Define a generic class with one parameter. The parameter
// has three constraints: It must inherit TestBase, it must
// implement ITestArgument, and it must have a parameterless
// constructor.
public class Test<T> where T : TestBase, ITestArgument, new() {}// Define a class that meets the constraints on the type
// parameter of class Test.
public class TestArgument : TestBase, ITestArgument
{public TestArgument() {}
}public class Example
{// The following method displays information about a generic// type.private static void DisplayGenericType(Type t){Console.WriteLine("\r\n {0}", t);Console.WriteLine(" Is this a generic type? {0}",t.IsGenericType);Console.WriteLine(" Is this a generic type definition? {0}",t.IsGenericTypeDefinition);// Get the generic type parameters or type arguments.Type[] typeParameters = t.GetGenericArguments();Console.WriteLine(" List {0} type arguments:",typeParameters.Length);foreach( Type tParam in typeParameters ){if (tParam.IsGenericParameter){DisplayGenericParameter(tParam);}else{Console.WriteLine(" Type argument: {0}",tParam);}}}// The following method displays information about a generic// type parameter. Generic type parameters are represented by// instances of System.Type, just like ordinary types.private static void DisplayGenericParameter(Type tp){Console.WriteLine(" Type parameter: {0} position {1}",tp.Name, tp.GenericParameterPosition);Type classConstraint = null;foreach(Type iConstraint in tp.GetGenericParameterConstraints()){if (iConstraint.IsInterface){Console.WriteLine(" Interface constraint: {0}",iConstraint);}}if (classConstraint != null){Console.WriteLine(" Base type constraint: {0}",tp.BaseType);}else{Console.WriteLine(" Base type constraint: None");}GenericParameterAttributes sConstraints =tp.GenericParameterAttributes &GenericParameterAttributes.SpecialConstraintMask;if (sConstraints == GenericParameterAttributes.None){Console.WriteLine(" No special constraints.");}else{if (GenericParameterAttributes.None != (sConstraints &GenericParameterAttributes.DefaultConstructorConstraint)){Console.WriteLine(" Must have a parameterless constructor.");}if (GenericParameterAttributes.None != (sConstraints &GenericParameterAttributes.ReferenceTypeConstraint)){Console.WriteLine(" Must be a reference type.");}if (GenericParameterAttributes.None != (sConstraints &GenericParameterAttributes.NotNullableValueTypeConstraint)){Console.WriteLine(" Must be a non-nullable value type.");}}}public static void Main(){// Two ways to get a Type object that represents the generic// type definition of the Dictionary class.//// Use the typeof operator to create the generic type// definition directly. To specify the generic type definition,// omit the type arguments but retain the comma that separates// them.Type d1 = typeof(Dictionary<,>);// You can also obtain the generic type definition from a// constructed class. In this case, the constructed class// is a dictionary of Example objects, with String keys.Dictionary<string, Example> d2 = new Dictionary<string, Example>();// Get a Type object that represents the constructed type,// and from that get the generic type definition. The// variables d1 and d4 contain the same type.Type d3 = d2.GetType();Type d4 = d3.GetGenericTypeDefinition();// Display information for the generic type definition, and// for the constructed type Dictionary<String, Example>.DisplayGenericType(d1);DisplayGenericType(d2.GetType());// Construct an array of type arguments to substitute for// the type parameters of the generic Dictionary class.// The array must contain the correct number of types, in// the same order that they appear in the type parameter// list of Dictionary. The key (first type parameter)// is of type string, and the type to be contained in the// dictionary is Example.Type[] typeArgs = {typeof(string), typeof(Example)};// Construct the type Dictionary<String, Example>.Type constructed = d1.MakeGenericType(typeArgs);DisplayGenericType(constructed);object o = Activator.CreateInstance(constructed);Console.WriteLine("\r\nCompare types obtained by different methods:");Console.WriteLine(" Are the constructed types equal? {0}",(d2.GetType()==constructed));Console.WriteLine(" Are the generic definitions equal? {0}",(d1==constructed.GetGenericTypeDefinition()));// Demonstrate the DisplayGenericType and// DisplayGenericParameter methods with the Test class// defined above. This shows base, interface, and special// constraints.DisplayGenericType(typeof(Test<>));}
}