参考微软说明: 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)
{
//ITestArgument
var itestArgumentName = iConstraint.Name;
}
else
{
//TestBase
var 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<>));
}
}