Type T1 = typeof(TClass); T1.GetMethod(, BindingFlags.Instance | BindingFlags.Public).Invoke( }); T1.GetMethod(, BindingFlags.Instance | BindingFlags.Public).Invoke(new TClass(), null); T1.GetMethod(, BindingFlags.Static | BindingFlags.Public).Invoke(T1, null);
使用其实和上面的方式一区别不大。
真正的全动态调用上面的两种方式,在编写代码的时候总是要先确定了已知的对象名和方法名。那么我们在不知道对象和方法名的时候是否也可以调用呢?答案是肯定的,实现如下:
Console.WriteLine(); string className = Console.ReadLine(); Console.WriteLine(); string funName = Console.ReadLine(); Type T1 = Type.GetType(className); ConstructorInfo ci = T1.GetConstructors()[obj = ci.Invoke(null);//实例化构造函数 T1.InvokeMember(funName, BindingFlags.InvokeMethod, null, obj, null);
当然,这个代码只能只是fun2,因为上面的传参写死了。(你也可以自己稍微修改下,就可以执行fun、fun2、fun3了)
效果如下:(对象名和方法名都是手动输入的)
我们先定义一个对象:
public class TClass { public TClass() { Console.WriteLine(); } public TClass(string str) { Console.WriteLine(+ str); } }
动态构造对象
//动态构造对象,方式一 Assembly asm = Assembly.GetExecutingAssembly(); TClass obj = (TClass)asm.CreateInstance(, true);//true:不区分大小写 //动态构造对象,方式二 ObjectHandle handler = Activator.CreateInstance();//null:当前程序集 obj = (TClass)handler.Unwrap(); //动态构造对象,方式三(构造有参构造函数) Assembly asm2 = Assembly.GetExecutingAssembly(); obj = (TClass)asm2.CreateInstance(, }, null, null);//true:不区分大小写
执行效果图:
获取和修改属性var obj = new TClass(); obj.name = ; Type type = typeof(TClass); Name = type.InvokeMember(, BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance, null, obj, ; Console.WriteLine(obj.name); //设置属性 type.InvokeMember(, BindingFlags.SetProperty | BindingFlags.Public | BindingFlags.Instance, null, obj, }); Console.WriteLine(obj.name);
从程序集中获得类型 取得当前代码所在程序集(使用GetExecutingAssembly)Assembly ass = Assembly.GetExecutingAssembly(); Console.WriteLine("当前所在程序集名:"+ass.ManifestModule.Name); Console.WriteLine("当前所在程序集路径:"+ass.Location);
通过反射加载程序集并创建程序中的类型对象
从程序集中获得类型,这个应该是我们平时用得比较多。如我们所谓的依赖注入和控制反转(这个主题将在下篇博文进行分析)就用到了通过反射从程序集中获取类型。
首先我们还是看看怎么从程序集中获得类型吧。我们可以使用Assembly类型提供的静态方法LoadFrom()或Load(),如:
Assembly asm = Assembly.LoadFrom(); Assembly asm = Assembly.Load();
区别:
Assembly asm = Assembly.LoadFrom();//需要加后缀,可以指定路径,如下面的 Assembly asm1 = Assembly.LoadFrom(); Assembly asm2 = Assembly.Load();//无需加后缀,不可以指定路径 这里会报错 //使用Load可以加载当前程序bin目录行下的程序集或者系统程序集 //这里TClass可以是一个接口,那么可以在外面的dll任意实现了。 TClass obj = (TClass)asm2.CreateInstance(, true);//true:不区分大小写 obj.fun();//***调用动态加载的dll中的方法***