43 通过反射获得泛型的实际类型参数

 

 

public static void applyVector(Vector<Date> v1){}
Method meth=GenericTest.class.getMethod("applyVector", Vector.class);
		Type[] types=meth.getGenericParameterTypes();
		ParameterizedType pys=(ParameterizedType) types[0];//ParameterizedType类型是Tpye类型其中之一的儿子
		System.out.println(pys.getRawType());//得到她的原始类型//class java.util.Vector
		System.out.println(pys.getActualTypeArguments()[0]);//得到实际的类型参数,注意他是个数组,因为他可能有多个,例如HashMap<K,V>//class java.util.Vector

 

 

l  示例代码:

 

	Class GenericalReflection {
		  private Vector<Date> dates = new Vector<Date>();
		  public void setDates(Vector<Date> dates) {
		    this.dates = dates;
		  }
		  public static void main(String[] args) {
		   Method methodApply = GenericalReflection.class.getDeclaredMethod("applyGeneric", Vector.class);
		   ParameterizedType pType = (ParameterizedType)
		                    (methodApply .getGenericParameterTypes())[0];
		            System.out.println("setDates("
		                    + ((Class) pType.getRawType()).getName() + "<"
		                    + ((Class) (pType.getActualTypeArguments()[0])).getName()
		                    + ">)" );
		  }
	}

 

 

l  泛型DAO的应用:

Ø  public abstract class DaoBaseImpl<T> implements DaoBase<T> {

 

       protected Class<T> clazz;

       public DaoBaseImpl() {

              Type type = this.getClass().getGenericSuperclass();

              ParameterizedType pt = (ParameterizedType) type;

              this.clazz = (Class) pt.getActualTypeArguments()[0];

              System.out.println("clazz = " + this.clazz);

       }

      }

Ø  public class ArticleDaoImpl extends DaoBaseImpl<Article> implements ArticleDao {

       }

 

 

 

 

 

 

 

<think>我们面对的问题:通过反射获取基类为类型,并实例化该类型。 具体来说,假设我们有一个基类,比如`Base<T>`,然后有一个派生类`Derived`继承自`Base<SomeClass>`。现在,我们想通过反射从`Derived`类型获取其基类的参数(即`SomeClass`),然后创建`SomeClass`的实例。 步骤: 1. 获取当前类型(例如`Derived`)的基类(即`Base<SomeClass>`)。 2. 检查基类是否是类型,并且是类型的定义(即`Base<>`)的实例。 3. 获取基类的参数(即`SomeClass`)。 4. 使用反射创建参数的实例。 参考引用[4]中展示了Java的类似做法,但我们需要C#的实现。 在C#中,我们可以通过以下步骤实现: 步骤分解: 1. 获取当前类型的基类:使用`Type.BaseType`属性。 2. 检查基类是否是类型:使用`Type.IsGenericType`属性。 3. 获取类型定义:使用`Type.GetGenericTypeDefinition()`方法,并与我们期望的基类定义(如`Base<>`)比较。 4. 获取参数:使用`Type.GetGenericArguments()`方法。 5. 创建参数的实例:使用`Activator.CreateInstance`方法。 示例代码: 假设有以下类定义: ```csharp public abstract class Base<T> { public T Data { get; set; } } public class Derived : Base<string> { } ``` 现在,我们想通过`Derived`类型获取其基类的参数(即`string`),并创建一个`string`的实例(这里只是示例,实际上字符串实例可以直接创建,但对于其他类型同样适用)。 但是,我们通常需要的是参数类型,然后创建该类型的实例。 具体实现: ```csharp using System; public class ReflectionHelper { public static object CreateGenericParameterInstance(Type derivedType) { // 获取基类 Type baseType = derivedType.BaseType; // 检查基类是否是类型 if (baseType != null && baseType.IsGenericType) { // 获取类型定义(即Base<>) Type genericBaseDefinition = baseType.GetGenericTypeDefinition(); // 假设我们期望的基类定义是Base<>,这里用实际类型比较 if (genericBaseDefinition == typeof(Base<>)) { // 获取参数数组 Type[] genericArguments = baseType.GetGenericArguments(); if (genericArguments.Length > 0) { Type genericArgumentType = genericArguments[0]; // 创建参数的实例 return Activator.CreateInstance(genericArgumentType); } } } return null; } } ``` 使用示例: ```csharp class Program { static void Main(string[] args) { // 获取Derived类型的基类参数并实例化 object instance = ReflectionHelper.CreateGenericParameterInstance(typeof(Derived)); // 因为Derived继承自Base<string>,所以instance应该是string的实例,即空字符串 Console.WriteLine(instance == null ? "null" : instance.ToString()); // 输出空字符串 } } ``` 注意: 1. 上述代码假设基类只有一个参数。如果有多个,需要根据具体情况处理。 2. `Activator.CreateInstance`方法要求类型具有无参构造函数,否则会抛出异常。如果需要支持带参数的构造函数,可以使用`Activator.CreateInstance`的其他重载。 如果基类有多个参数,我们可以获取所有参数并分别处理。但根据问题,我们只关注第一个参数(或者根据需求选择特定位置的参数)。 另外,引用[3]中提到,为了避免代码膨胀,建议将非方法放在非基类中。但我们的问题不涉及此。 引用[1]和[2]介绍了C#的基础知识,但我们的问题主要涉及反射。 相关问题: 1. 如何通过反射获取类的类型参数? 2. 当参数没有无参构造函数时,如何实例化? 3. 如何获取继承层次中所有基类的类型参数? 4. 如何动态创建类的实例(例如`List<T>`)? 下面我们将按照要求,在回答中自然地添加引用标识,并生成相关问题。</think>### C# 反射获取基类参数并实例化 在 C# 中通过反射获取基类的类型参数并实例化,需要以下步骤: #### 实现步骤 1. **获取基类类型** ```csharp Type derivedType = typeof(YourDerivedClass); Type baseType = derivedType.BaseType; // 获取直接基类 ``` 2. **检查并提取参数** ```csharp if (baseType.IsGenericType && baseType.GetGenericTypeDefinition() == typeof(YourGenericBaseClass<>)) { Type[] typeArguments = baseType.GetGenericArguments(); Type genericParamType = typeArguments[0]; // 获取第一个参数 } ``` 3. **实例化参数类型** ```csharp object instance = Activator.CreateInstance(genericParamType); ``` #### 完整示例 ```csharp using System; // 基类定义 public abstract class GenericBase<T> { public T Data { get; set; } } // 派生类 public class StringDerived : GenericBase<string> { } class Program { static void Main() { Type derivedType = typeof(StringDerived); Type baseType = derivedType.BaseType; if (baseType.IsGenericType && baseType.GetGenericTypeDefinition() == typeof(GenericBase<>)) { Type genericType = baseType.GetGenericArguments()[0]; object instance = Activator.CreateInstance(genericType); Console.WriteLine($"创建类型: {genericType.Name}"); // 输出: String Console.WriteLine($"实例类型: {instance.GetType().Name}"); // 输出: String } } } ``` #### 关键点说明 1. **`Type.IsGenericType`** 检查类型是否为类型[^1] 2. **`GetGenericTypeDefinition()`** 获取类型定义(不带具体类型参数)[^2] 3. **`GetGenericArguments()`** 获取实际类型参数数组[^4] 4. **`Activator.CreateInstance()`** 动态创建实例(需要无参构造函数) #### 处理复杂情况 当参数需要构造函数参数时: ```csharp // 创建带参数的实例 object instance = Activator.CreateInstance( genericType, new object[] { "构造参数" } ); ``` #### 性能优化建议 参考引用[3]的建议: ```csharp // 推荐结构:非基类 + 派生类 public abstract class BaseClass // 非基类 { // 非方法 } public class GenericDerived<T> : BaseClass // 派生类 { // 相关方法 } ``` 此结构可减少代码膨胀,避免重复编译非方法[^3]。 ### 相关问题 1. 如何获取多层继承中的基类参数? 2. 当参数是值类型(如`int`)时,`CreateInstance`会返回什么? 3. 如何检查类型约束(如`where T : new()`)? 4. 反射创建类型实例的性能优化方法有哪些? 5. 如何处理嵌套类型(如`GenericBase<List<string>>`)的反射? > 通过反射操作类型时,需注意类型安全和性能影响,建议在复杂场景中使用约束或设计模式替代方案[^1][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值