泛型约束的反射,使用,以及内部类

 

try

Type   type   =   Type.GetType( "test.CTest`1,   MyTest ");

also   see
Reflection   support   for   generic   types   in   .NET   Compact   Framework
 
==
 
刚才我终于搞到了MSDN   2005,查到了相关的方法.获取类型时候,用   思归   说的那种写法.
然后,利用MakeGenericType   来生成Generic的Type,然后就可以configObject   =   Activator.CreateInstance(type,   parameters);了.

看来,最新的MSDN和书籍/网络资料,都不可缺少阿.   C#的范型和C++的区别不少,得仔细看看MSDN了.
 
中文参考:

转载地址:

Reflection support for generic types in .NET Compact Framework

25 Jan 2005 2:33 PM
  • Comments 3

Version 2 of .NET Compact Framework (NETCF) will provide support for parametric polymorphism aka Generics. You can get a good feel for the feature support from blog posts by Seth Demsey and Roman Batoukov. It would also be useful to go over Generics terminology as presented in this article in section 1.1.

 

Evidently since this language feature adds to the very nature of types in the CLR, one could safely assume need for special support when reflecting on these types … and such is the case. Below is a list of new Reflection APIs provided to assist in discovering information about a generic type/method through reflection. It should be noted however that previously existent reflection APIs like Type.GetMethods() etc would also discover generic methods and the like.

 

 

 

I. New Reflection APIs for generic support.

 

(Note: This list is current as of .NET Framework 2.0 Beta 1 and may change henceforth.)


 

1. System.Type

 

Properties

ContainsGenericParameters

HasGenericArguments

IsGenericParameter

IsGenericTypeDefinition

 

Methods

BindGenericParameters

GetGenericArguments

GetGenericTypeDefinition

 

 

2. System.Reflection.MethodInfo

 

Properties

ContainsGenericParameters

HasGenericArguments

IsGenericMethodDefinition

 

Methods

BindGenericParameters

GetGenericArguments

GetGenericMethodDefinition

 

 

 

II. How and where would I use it?


 

1. Creating generic types via reflection.

 

NETCF does not have runtime IL verification and metadata validation and hence cannot validate generic parameter constraints for normal execution scenarios (if the compiler did not catch the error at compile time). However, if one were to use reflection, i.e. get an open generic type and the bind parameters to it via BindGenericParameters() API, constraint validation would be performed. So if constraint validation is important to you, use the reflection API to bind parameters (if the compiler would not catch the error). Here is an example:

 

Say I have a generic type:

 

public class MyGenericType<T, U>

   where T: IFormattable

   where U: IConvertible

{}

 

Something like MyGenericType<Int32, Object> should not be allowed, since System.Object does not implement IConvertible. However if you were to write code that looked as below, we would validate the constraints on MyGenericType and throw an exception.

 

Type foo = Type.GetType("MyGenericType`2");

Type[] params = new Type[] {typeof(Int32), typeof(Object)};

Type bar = foo.BindGenericParameters(params); // This will throw an exception because constraints are not met.

 

Type foo above denotes the open type for MyGenericType, meaning no generic parameters have been bound to it yet. The open type is also referred to as the Generic Type Definition. The "`2" (back-tick) notation refers to the number of generic parameters on the type. So a class like

 

public class GenType2<T1, T2, T3, T4>

 

would have an open type notation of

 

Type foo2 = Type.GetType("GenType2`4");

 

Creating a bound type for GenType2 would look something like what is shown below. As one would guess, the types foo3, foo4 and foo5 are identical.

 

Type foo3 = Type.GetType("GenType2`4[System.Int32, System.Int32, System.Int32, System.Int32]");

GenType2<Int32, Int32, Int32, Int32> bar2 = new GenType2<Int32, Int32, Int32, Int32>();

Type foo4 = bar2.GetType();

Type foo5 = typeof(GenType2<Int32, Int32, Int32, Int32>);

 

What would the type string look like if one of the generic parameters above was a type in a different assembly? Well it would look something like what is shown below.

 

Type foo6 = Type.GetType("MyGenericClass`2[System.Int32, [MyNameSpace.MyExternType, MyExternAssemblyName]]");

 

Of course you could also go ahead and provide more information like the public key token if you wanted.

 

 

2. Invoking generic methods and methods with generic arguments using reflection

 

Say I have the following type definition.

 

public class MyGenericType <T, U>

{

   public void Method1 (T x) {}

   public void Method2<V> () {}

}

 

Method1 is a method which has a generic argument and Method2 would be a generic method. Hopefully this example helped untangling your brain from the topic being discussed. In Method1, the first argument x happens to be of the same type as the first generic parameter that MyGenericType was created with (T). In Method2 however, V is a generic type and has no relation to the generic parameters used to create MyGenericType. Here's how these methods would be called in the normal execution scenario.

 

MyGenericType<Int32, Double> mgt = new MyGenericType<Int32, Double>();

Int32 i = 0;

mgt.Method1( i );

mgt.Method2<System.DateTime>();

 

Here's how you would do it using reflection.

 

MethodInfo mi1 = typeof(mgt).GetMethod("Method1");

MethodInfo mi2 = typeof(mgt).GetMethod("Method2");

mi1.Invoke(mgt, new object[] {5}); // The method argument has to be castable to an Int32.

MethodInfo mi2_bound = mi2.BindGenericParameters(typeof(System.DateTime));

mi2_bound.Invoke(mgt, new object[] {});

MethodInfo mi2_unbound = mi2_bound.GetGenericMethodDefinition();

 

As you noticed we had to first bind a generic parameter to Method2 before we could Invoke it. In the code above, mi2_unbound would be the same as mi2.

 

 

 

III. Limitations


 

1. Getting members of open generic types

 

Getting members, methods or interfaces of open generic types is not supported in NETCF. You will get a NotSupportedException thrown when you attempt to do something similar to what is shown below.

 

Type t = Type.GetType("MyGenericType`2");

Type[] InterfaceList = t.GetInterfaces() // This will throw a NotSupportedException

MethodInfo mi = t.GetMethod("Method1"); // This will throw a NotSupportedException

 

What you would need to do to work around this is to simply bind some type parameters to your generic type (instantiate it) and then attempt to get its members.

 

Type t = Type.GetType("MyGenericType`2[System.Int32, System.Int32]");

MethodInfo mi = t.GetMethod("Method1"); // This will work.

 

 

2. Methods/Properties not supported on formal types

 

If you were to call GetGenericArguments() on an open generic type, you would get the generic parameter list ... also called formal parameters.

 

Type t = Type.GetType("MyGenericType`2");

Type[] genargs = t.GetGenericArguments();

 

The array genargs would actually contain the type T and U as defined in the class definition. You are limited to what you can actually call on this formal type. Attempting to access BaseType, DeclaringType, ReflectedType etc. would result in a NotSupportedException being thrown. This is also true if you attempt to get interfaces, methods or members on it.

 

 

3. Discovering constraints on parameters through reflection.

 

NETCF does not support the GetGenericParameterConstraints() API and as such you will not be able to look up the constraints on generic parameters of any generic type/method through reflection. Another mechanism that the full .NET framework provides for discovering this is through discovery on formal parameters, but the restrictions on formal parameters stated above in III.2 would prevent you from doing this on NETCF. This restriction is further elaborated in IV.2.

 

 

4. Can't resolve method signature ambiguities because of lack of reflection on open types.

 

Say I have a type definition that looks something as shown below.

 

public class Generic2P <T, U>

{

   public void method (T x) {}

   public void method (U y) {}

}

 

public class Generic1P <R>

{

   public void method<S>(S s)

   {

      Generic2P<R, S> foo = new Generi2P<R, S>();

      foo.method(s);

   }

}

 

If for the instantiation of Generic1P's method has the same type used for both its generic parameters R and S, then it would result in ambiguity as to which method would be called on Generic2P. For example if I have

 

Generic1P<int> bar = new Generic1P<int>();

bar.method<int>(5);

 

Then this would result in Generic2P<int, int> getting created and Generic2P<int, int>.method(int) being called. However there will be two methods with this exact same signature. Both NETCF and the full .NET framework will default to the same method, but what if that is not the method you want to call?

 

On the full .NET framework one could get methods on the open type Generic2P<T, U> and based on the formal parameter used as the argument in the method, you could fetch the right method and bind parameters/arguments to it and invoke it. However since we can not get methods or members on open types in NETCF we would not be able to do this and you would not be able to manually resolve signature ambiguities.

 

 

 

IV. Differences with the full .NET Framework


 

1. Lack of TargetException, TargetInvocationException, TargetParameterCountException.

 

NETCF does not support the above mentioned exceptions that are thrown on the full .NET framework when one attempts to call BindGenericParameters() with illegal arguments. On NETCF the following substitutions occur.

 

TargetException -> ArgumentNullException, InvalidProgramException

TargetInvocationException -> MissingMethodException

TargetParameterCountException -> ArgumentException.

 

 

2. Constraint hierarchy vs. Derivation hierarchy.

 

Consider the following type definitions.

 

public interface InterfaceA {}

public interface InterfaceB {}

public class BaseA: InterfaceA {}

public class InheritedA: BaseA, InterfaceB {}

 

public class BaseB<T>

   where T: InterfaceA

{}

 

public class InheritedB<T>

   where T: BaseB<T>, InterfaceB

{}

 

In the case of InheritedA, it inherits from BaseA that implements InterfaceA. This hierarchy would constitute the derivation hierarchy. In the case of InheritedB, its generic parameter is constrained to inheriting from BaseB<T>, whose generic parameter is constrained to implementing InterfaceA. This hierarchy would constitute the constraint hierarchy.

 

On the full .NET framework, if we were to get the formal type T via a call to GetGenericArguments() on the open type InheritedB; we could traverse the constraint hierarchy as if it were a derivation hierarch by using the BaseType property and calling GetInterfaces() method on it. In NETCF however we distinguish between the two and do not allow you to treat constraint hierarchy as if it were a derivation hierarchy. So you cannot use the BaseType property and the GetInterfaces() method to peruse the constraint hierarchy. Instead you would get a NotSupportedException thrown at you.

 

 

 

3. Differences in exceptions thrown.

 

There are many places where we throw MissingMethodExceptions instead of ArgumentExceptions and the like. Hopefully this will be addressed in another blog post that will be soon to come.

 


This posting is provided "AS IS" with no warranties, and confers no rights.

嵌套类型(C# 编程指南)

结构内部定义的类型称为嵌套类型。例如:

C#
class Container
{
    class Nested
    {
        Nested() { }
    }
}


不管外部类型是类还是结构,嵌套类型均默认为 private,但是可以设置为 public、protected internal、protectedinternalprivate在上面的示例中,Nested 对外部类型是不可访问的,但可以设置为 public,如下所示:

C#
class Container
{
    public class Nested
    {
        Nested() { }
    }
}


嵌套类型(或内部类型)可访问包含类型(或外部类型)。 若要访问包含类型,请将其作为构造函数传递给嵌套类型。 例如:

C#
public class Container
{
    public class Nested
    {
        private Container parent;

        public Nested()
        {
        }
        public Nested(Container parent)
        {
            this.parent = parent;
        }
    }
}
 
  C#中的内部类能够使用外部类定义的类型和静态方法,但是不能直接使用外部类的实例方法,直接看来,外部类对于内部类的作用更像是一个命名空间,在C#中,始终可以用(只要访问控制允许)
Sys.Model.Key   key = new Model.Key();  
来创建一个内部类的实例,这个实例与外部类的任何实例没有任何直接的关系。类似于Java中的静态内部类。   
       在C#中,类区分为Nested Class和Not-Nested Class,前者是声明在其他数据类型内部的类。后者是直接定义在某一个命名空间的类。 
   
      非内嵌类只允许使用public和internal的访问控制,而内置类则允许使用所有的五种访问控制符,private, protected , internal protected,public和internal。内部类也可以访问外部类的所有方法,包括instance方法和private方法,但是需要显式的传递一个外部类的实例。 
       创建内部类的一个目的是为了抽象外部类的某一状态下的行为,或者内部类仅在外部类的某一特定上下文存在。或是隐藏实现,通过将内部类设为private,可以设置仅有外部类可以访问该类。内部类的另外一个重要的用途是当外部类需要作为某个特定的类工作,而外部类已经继承与另外一个类的时候,因为C#不支持多继承,所以创建一个对应的内部类作为外部类的一个façade来使用.
       内部类的反射名称的.改为+,例如:Sys.Model+Key【其中Key是Model的内部类】    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值