在C#中,反射对于单个对象实现了类环境中的层次检索;对于相关的多个类间(class groups)实现了运行时的动态调用与创建。后者,更多地用于抽象工厂类的对象创建环境中。
基本知识:
用到System.Reflection、System.Activator或System.Object类;
1.读取
(1)单个对象,使用System.Object的GetType方法,即可。
using System; using System.Reflection; class TypeObjectFromInstanceApp { public static void Main(string[] args) { int i = 6; Type type = i.GetType(); Console.WriteLine(type.Name); } }
(2)或,使用System.Type的GetType方法,
public static Type GetType(string name);
public static Type GetType(string name, bool throw);
public static Type GetType(string name, bool throw,bool ignoreCase);
using System; using System.Reflection; class TypeObjectFromNameApp { public static void DisplaySyntax() { Console.WriteLine("\nSyntax: TypeObjectFromName " + "<typename>\n"); } public static void DisplayTypeInfo(string typename) { try { Type type = Type.GetType(typename, true); Console.WriteLine("\n'{0}' is located in the " + "module {1}", typename, type.Module); } catch(TypeLoadException e) { Console.WriteLine("\n'{0}' could not be " + "located. Did you qualify with a namespace?", typename); } } public static void Main(string[] args) { if (1 != args.Length) DisplaySyntax(); else DisplayTypeInfo(args[0]); } }
2.创建
(1)多类间根据需要动态地创建对象,主要是System.Activator类,CreateInstance(type parameter)方法,如下:
using System; using System.Reflection; class AbstractFactory { public IReflect CreateObject(string classname) { IReflect objreflect; try { // Create the type, throwing an exception // if it can't be created. System.Type oType = System.Type.GetType(classname,true); // Create an instance and type-cast it // to our interface. objreflect = (IReflect)System.Activator.CreateInstance( oType); } catch(TypeLoadException e) { throw new InvalidOperationException("Type could " + "not be created. Check innerException " + "for details", e); } return objreflect; } }; public interface IReflect { string Name { get; } }; class Reflect1 : IReflect { public string Name { get { return "Reflect 1"; } } }; class Reflect2 : IReflect { public string Name { get { return "Reflect 2"; } } } class AbstractFactoryApp { static void Main(string[] args) { callReflection(args[0]); } static void callReflection(string strClassName) { IReflect objReflect; AbstractFactory objFactory = new AbstractFactory(); try { objReflect = objFactory.CreateObject(strClassName); Console.WriteLine("You constructed a {0} object", objReflect.Name); } catch(Exception e) { Console.WriteLine("ERROR: {0}\n{1}", e.Message, (null == e.InnerException ? "" : e.InnerException.Message)); } Console.ReadLine(); } };
(2)全程创建(类型及对象)
// ILGenServer.cs – compile as follows: // csc /t:library ILGenServer.cs using System; using System.Reflection; using System.Reflection.Emit; namespace ILGenServer { public class CodeGenerator { public CodeGenerator() { // Get current currentDomain. currentDomain = AppDomain.CurrentDomain; // Create assembly in current currentDomain. assemblyName = new AssemblyName(); assemblyName.Name = "TempAssembly"; assemblyBuilder = currentDomain.DefineDynamicAssembly( assemblyName, AssemblyBuilderAccess.Run); // Create a module in the assembly. moduleBuilder = assemblyBuilder.DefineDynamicModule( "TempModule"); // Create a type in the module. typeBuilder = moduleBuilder.DefineType("TempClass", TypeAttributes.Public); // Add a member (a method) to the type. methodBuilder = typeBuilder.DefineMethod( "HelloWorld", MethodAttributes.Public, null, null); // Generate MSIL. msil = methodBuilder.GetILGenerator(); msil.EmitWriteLine("Hello World"); msil.Emit(OpCodes.Ret); // Last "build" step : create type. type = typeBuilder.CreateType(); } AppDomain currentDomain; AssemblyName assemblyName; AssemblyBuilder assemblyBuilder; ModuleBuilder moduleBuilder; TypeBuilder typeBuilder; MethodBuilder methodBuilder; ILGenerator msil; object obj; Type type; public Type T { get { return this.type; } } }; // End of CodeGenerator class }; // End of ILGenServer namespace
客户端调用上面编译后的dll,如下:
// ILGenClient.cs – compile as follows: // csc ILGenClient.cs /r:ILGenServer.dll using System; using System.Reflection; using ILGenServer; public class ILGenClientApp { public static void Main() { Console.WriteLine("Calling DLL function to generate " + "a new type and method in memory..."); CodeGenerator gen = new CodeGenerator(); Console.WriteLine("Retrieving dynamically " + "generated type..."); Type t = gen.T; if (null != t) { Console.WriteLine("Instantiating the new type..."); object o = Activator.CreateInstance(t); Console.WriteLine("Retrieving the type's " + "HelloWorld method..."); MethodInfo helloWorld = t.GetMethod("HelloWorld"); if (null != helloWorld) { Console.WriteLine("Invoking our dynamically " + "created HelloWorld method..."); helloWorld.Invoke(o, null); } else { Console.WriteLine("Could not locate " + "HelloWorld method"); } } else { Console.WriteLine("Could not access Type " + "from server"); } } }
小结,如果说“委托”实现了对同构函数(类成员层面)的抽象,那么“反射”提供了对“同性对象”(类层面)全面的动态运行时干预能力。而对于latebinding,则更是直接衍生出了一种新的语法格式,即泛型(generics),一般用<T>表示。即,在运行时由客户端来确定实际的类型(也就是说,类型可变)。