`
guoyiqi
  • 浏览: 1014391 次
社区版块
存档分类
最新评论

使用反射检查和实例化泛型类型(转自:http://www.csharpwin.com/csharpspace/12241r3312.shtml)

 
阅读更多

与其他类型的信息一样,泛型类型的信息的获取方式为:检查表示泛型类型的Type对象。主要的差异在于,泛型类型具有一组表示其泛型类型参数的Type对象。本部分的第一个步骤是检查泛型类型。

通过将类型变量绑定到泛型类型定义的类型参数,可以创建表示构造类型的Type对象。第二个步骤演示此过程。

检查泛型类型及其类型参数

  1. 获取表示泛型类型的Type实例。在下面的代码中,使用 C# 的typeof运算符(在 Visual Basic 中为GetType,在 Visual C++ 中为typeid)获取类型。有关获取Type对象的其他方法,请参见Type类主题。注意,余下的步骤中,类型包含在名为t的方法参数中。

    C#

    Type d1 =typeof(Dictionary<,>);

  2. 使用IsGenericType属性确定类型是否为泛型,然后使用IsGenericTypeDefinition属性确定类型是否为泛型类型定义。

    C#

    Console.WriteLine(" Is this a generic type? {0}",
    t.IsGenericType);
    Console.WriteLine(" Is this a generic type definition? {0}",
    t.IsGenericTypeDefinition);

  3. 使用GetGenericArguments方法获取包含泛型类型参数的数组。

    C#

    Type[] typeParameters = t.GetGenericArguments();

  4. 对每个类型变量,使用IsGenericParameter属性确定其是不是类型参数(例如,在泛型类型定义中),是不是已为类型参数指定的类型(例如,在构造类型中)。

    C#

    Console.WriteLine(" List {0} type arguments:",
    typeParameters.Length);
    foreach( Type tParamintypeParameters )
    {
    if(tParam.IsGenericParameter)
    {
    DisplayGenericParameter(tParam);
    }
    else
    {
    Console.WriteLine(" Type argument: {0}",
    tParam);
    }
    }

  5. 在类型系统中,和普通类型一样,泛型类型参数是由Type的实例表示的。下面的代码演示表示泛型类型参数的Type对象的名称和参数位置。此处,参数位置无足轻重;它在检查类型参数(用作其他泛型类型的类型变量)时更有价值。

    C#

    private
    staticvoidDisplayGenericParameter(Type tp)
    {
    Console.WriteLine(" Type parameter: {0} position {1}",
    tp.Name, tp.GenericParameterPosition);

  6. 通过使用GetGenericParameterConstraints方法获取单个数组中的所有约束,确定泛型类型参数的基类型约束和接口约束。不保证约束处于任何特定顺序。

    C#

    Type classConstraint =null;

    foreach(Type iConstraintintp.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");

  7. 使用GenericParameterAttributes属性获取类型参数的特殊约束,如要求其为引用类型。该属性还包含表示方差的值,该值可屏蔽,如下面的代码所示。

    C#

    GenericParameterAttributes sConstraints =
    tp.GenericParameterAttributes &
    GenericParameterAttributes.SpecialConstraintMask;

  8. 特殊约束的属性为标志,表示没有任何特殊约束的标志 (System.Reflection.GenericParameterAttributes.None) 还表示没有协变或逆变。因此,若要测试其中一个条件,必须使用适当的屏蔽。在此情况下,请使用System.Reflection.GenericParameterAttributes.SpecialConstraintMask隔离特殊约束标志。

    C#

    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.");
    }
    }

构造泛型类型的实例

泛型类型和模板类似。除非指定其泛型类型参数的实际类型,否则不能创建泛型类型的实例。若要在运行时使用反射创建实例,需要使用MakeGenericType方法。

构造泛型类型的实例

  1. 获取表示泛型类型的Type对象。下面的代码以两种不同方式获取泛型类型Dictionary:一种方法使用System.Type.GetType(System.String)方法重载和描述类型的字符串,另一种方法调用构造类型Dictionary<String, Example>(在 Visual Basic 中为Dictionary(Of String, Example))的GetGenericTypeDefinition方法。MakeGenericType方法需要泛型类型定义。

    C#

    // 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 =newDictionary<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();

  2. 构造一组用于替换类型参数的类型变量。数组必须包含正确数目的Type对象,并且顺序和对象在类型参数列表中的顺序相同。在这种情况下,键(第一个类型参数)的类型为String,字典中的值是名为Example的类的实例。

    C#
    Type[] typeArgs = {typeof(string),typeof(Example)};

  3. 调用MakeGenericType方法将类型变量绑定到类型参数,然后构造类型。

    C#
    Type constructed = d1.MakeGenericType(typeArgs);

  4. 使用CreateInstance方法重载来创建构造类型的对象。下面的代码在生成的Dictionary<String, Example>对象中存储Example类的两个实例。

    C#

    object
    o = Activator.CreateInstance(constructed);

示例

下面的代码示例定义DisplayGenericType方法来检查泛型类型定义和代码中使用的构造类型,并显示它们的信息。DisplayGenericType方法演示如何使用IsGenericTypeIsGenericParameterGenericParameterPosition属性以及GetGenericArguments方法。

该示例还定义DisplayGenericParameter方法来检查泛型类型参数并显示其约束。

代码示例定义一组测试类型,包括说明类型参数约束的泛型类型,并演示如何显示这些类型的信息。

示例通过创建一组类型参数并调用MakeGenericType方法,从Dictionary类构造类型。程序对使用MakeGenericType构造的Type对象和使用typeof(Visual Basic 中为GetType)获取的Type对象进行比较,演示这两个对象是相同的。类似地,程序使用GetGenericTypeDefinition方法获取构造类型的泛型类型定义,并将其与表示Dictionary类的Type对象进行比较。

C#
usingSystem;
usingSystem.Reflection;
usingSystem.Collections.Generic;
usingSystem.Security.Permissions;

// Define an example interface.
publicinterfaceITestArgument {}

// Define an example base class.
publicclassTestBase {}

// 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.
publicclassTest<T>whereT : TestBase, ITestArgument,new() {}

// Define a class that meets the constraints on the type
// parameter of class Test.
publicclassTestArgument : TestBase, ITestArgument
{
publicTestArgument() {}
}

publicclassExample
{
// The following method displays information about a generic
// type.
privatestaticvoidDisplayGenericType(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 tParamintypeParameters )
{
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.
privatestaticvoidDisplayGenericParameter(Type tp)
{
Console.WriteLine(" Type parameter: {0} position {1}",
tp.Name, tp.GenericParameterPosition);

Type classConstraint =null;

foreach(Type iConstraintintp.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.");
}
}
}

[PermissionSetAttribute(SecurityAction.Demand, Name="FullTrust")]
publicstaticvoidMain()
{
// 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 =newDictionary<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);

objecto = 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<>));
}
}

分享到:
评论

相关推荐

    https://raw.githubusercontent.com/selva86/datasets/master/a10.csv

    https://raw.githubusercontent.com/selva86/datasets/master/a10.csv,时间序列分析基本方法和实例相关数据

    esp8266从入门到精通的实例,网上购买

    玩转ESP8266 SDK编程【实例】, 第1集(公开):套件介绍 观看地址:http://v.youku.com/v_show/id_XMTUzNzM3ODg3Mg==.html 操作演示:http://pan.baidu.com/s/1dEGjwVv(视频演示全家福) 第2集(加密):组装WIFI...

    3.java实例化泛型类.zip

    3.java实例化泛型类.zip3.java实例化泛型类.zip3.java实例化泛型类.zip3.java实例化泛型类.zip3.java实例化泛型类.zip3.java实例化泛型类.zip3.java实例化泛型类.zip3.java实例化泛型类.zip3.java实例化泛型类.zip3....

    iquery经典教程

    所有效果说明:基本的鼠标互动:拖拽(drag and dropping)、排序... CSS文件:http://dev.jquery.com/view/trunk/themes/flora/flora.all.css 选项说明:http://docs.jquery.com/UI/Tabs/tabs#initialoptions 选项实例:...

    Asp.net 调用淘宝客Top Api 接口 实例源码!

    //请去http://www.alimama.com 阿里妈妈网站得到一个pid帐号 如:mm_10594045_0_0 //没有App Key与App Secret 与mm_10594045_0_0 网站数据是没办法读取出来,以下的帐号我是随便填一个上去为了测试用的,数据是不显示...

    hge开发必备之开发包和实例

    OGRE, http://www.ogre3d.org/ 如果研究3D,不研究他,实在没道理 Irrlicht,http://irrlicht.sourceforge.net/ 虽然我将他定义为入门级的3D引擎,但功能很强大。 KlayGE,http://klayge.sourceforge.net/ 这是国人写...

    C语言编程思想

    C语言作为一门基础且强大的系统级编程语言,是许多现代编程语言的基础,对于软件开发人员来说,理解和熟练使用C语言至关重要。 在C语言编程中,以下几个关键知识点是学习的重点: 1. **数据类型**:C语言提供了...

    MFC控件应用讲解-按钮应用和自绘

    本博客近期每天推出MFC实例课程讲解,如果你对此感兴趣, 欢迎访问我的博客主页,http://www.gymsaga.com/ MFC专栏请进 --- http://www.gymsaga.com/category/project/developc/mfc 本次实例代码讲解地址:...

    [大家网]EXT JS源码分析与开发实例宝典[club.topsage.com].part4

    本书共分为5个分卷,要完全下载 资料来源:大家网http://club.topsage.com 也可以去这下载完本:http://club.topsage.com/thread-2602632-1-1.html

    JFreeChart 之四:JFreeChartUtil

    NULL 博文链接:https://xiaofengtoo.iteye.com/blog/1226856

    【编辑框CEdit】控件应用第七课

    本博客近期每天推出MFC实例课程讲解,如果你对此感兴趣, 欢迎访问我的博客主页,http://www.gymsaga.com/ MFC专栏请进 --- http://www.gymsaga.com/category/project/developc/mfc 本次实例代码讲解地址:...

    django项目实例(django 简易博客开发)

    前几天写的django 简易博客开发记录,贴个链接吧 ...django 简易博客开发 2 模板和数据查询 http://www.cnblogs.com/cacique/archive/2012/09/30/2709143.html django 简易博客开发 3 静态文件、from 应用与自定义 ...

    php网络编程技术与实例.rar

    (1)第1章所有实例的访问路径为“http://localhost/chap01/”,如访问helloworld.htm文件,可以输入如下路径:http://localhost/chap01/helloworld.htm (2)第2章所有实例的访问路径为“http://localhost/chap02/...

    c++ chm帮助文档 http://www.cplusplus.com

    它具有面向对象、泛型编程和过程化编程的特性,广泛应用于系统软件、应用软件、游戏开发、驱动程序、嵌入式系统以及大型企业级应用程序等各个领域。C++的语法严谨且高效,是许多现代编程语言的基础。 "C++ CHM帮助...

    图书馆管理信息系统.rar

    《C# 图书馆管理信息系统》是一个典型的软件开发实例,主要使用C#编程语言实现,旨在为图书馆提供高效、便捷的信息化管理方案。系统涵盖了图书的借阅、归还、续借、预约、查询等功能,同时也包括对读者信息的管理...

    利用Python实现酒店评论的中文情感分析-成品demo

    2)Gensim 用于主题模型、文档索引和大型语料相似度索引的python库,主要用于自然语言处理(NLP)和信息检索(IR)。下载地址:https://pypi.python.org/pypi/gensim 本实例中的维基中文语料处理和中文词向量模型...

    百度地图,定位自己+地图显示(在地图上显示自己当前位置,并覆盖自己的位置)

    在IT行业中,尤其是在移动开发和地理信息系统领域,地图API的使用是常见的需求。百度地图作为中国主流的地图服务提供商之一,提供了丰富的API接口供开发者使用。本文将深入探讨如何利用百度地图API实现“定位自己并...

    db2各版本下载地址全集

    - **易于管理:** 提供了图形化的管理工具,简化了数据库的安装、配置和维护过程。 #### 安装与配置 在安装DB2之前,请确保您的计算机满足所选版本的操作系统和硬件要求。具体步骤如下: 1. **下载安装程序:** ...

    最新版本的Struts2+Spring4+Hibernate4框架整合

    整合使用最新版本的三大框架(即Struts2、Spring4和Hibernate4),搭建项目架构原型。 项目架构原型:Struts2.3.16 + Spring4.1.1 + Hibernate4.3.6。 此外,还有:log4j、slf4j、junit4、ehcache等知识点。 项目...

    来自博客http://blog.csdn.net/uq_jin/article/details/51484890的代码

    12. **泛型**:从Java 5开始引入,泛型提高了代码的类型安全性,允许在编译时检查类型。 13. **注解(Annotation)**:自Java 5起,注解作为一种元数据,可以提供编译器和运行时系统使用的信息,用于代码的自动生成...

Global site tag (gtag.js) - Google Analytics