初学反射,在个人理解中,他的主要目的是为了让系统实现可扩展 可配置。
反射+配置文件+工厂 为例
先来一个接口类
public interface IShowFun
{
void Say();
void Do();
}
public class ShowGirlFun:IShowFun
{
public void Say()
{
Console.WriteLine("我是女生");
}
public void Do()
{
Console.WriteLine("我要穿裙子");
}
}
通过配置文件 记录 该方法的命名空间 和类全名
<appSettings> <add key="ShowGirlFun" value="ShowGirl,ShowGirl.ShowGirlFun"/> </appSettings>
设置一个工厂,读取配置文件,通过反射 创建并返回一个IShowFun对象
这里需要注意的是,如果用到读取配置文件 需要添加System.Configuration;引用
public class Factory
{
private static string txt = ConfigurationManager.AppSettings["ShowGirlFun"];
public static IShowFun CreateInstance()
{
string nametxt=txt.Split(',')[0];
string funtxt=txt.Split(',')[1];
Assembly assembly=Assembly.Load(nametxt);
Type type=assembly.GetType(funtxt);
return (IShowFun)Activator.CreateInstance(type);
}
}
调用代码
IShowFun fun = Factory.CreateInstance();
fun.Say();
fun.Do();
结果:
下面 ,如果我想修改一下,改成男生,只需要再新建一个男生的类库 然后继承IShowFun接口并实现,然后把男生单独生成的dll拷贝到调用方的bin/Debug下面,修改一下bin/Debug/?*.exe.config中的配置文件 即可
如下
添加一个男生
public class ShowBoyFun:IShowFun
{
public void Say()
{
Console.WriteLine("我是男生");
}
public void Do()
{
Console.WriteLine("我要穿裤子");
}
}
然后修改bin/Debug/?*.exe.config中的配置文件
把
<add key="ShowGirlFun" value="ShowGirl,ShowGirl.ShowGirlFun"/>
改成
<add key="ShowGirlFun" value="ShowBoy,ShowBoy.ShowBoyFun"/>
之后 运行exe程序 会发现发生了变化
多参数构造函数调用
创建构造参数为有参数的,只需要在创建的时候,按照先后顺序,把参数写进去就可以了,如下
Assembly assembly=Assembly.Load(nametxt);
Type type=assembly.GetType(funtxt);
return (IShowFun)Activator.CreateInstance(type,"啊啊啊",11);
这样 就创建了一个 有2个参数,分别是string和int的构造函数,他会根据参数的类型和数量,自动去匹配相对应的构造函数
破坏单例
反射可以突破访问限制,直接调用私有构造函数
比如现在做一个单例模式
public class Singleton
{
private Singleton()
{
Console.WriteLine("构造函数被运行一次");
}
private static Singleton singleton = new Singleton();
public Singleton CreateInstance()
{
return singleton;
}
}
通过反射进行调用
Console.WriteLine("********************破坏单例**********************");
Assembly assembly = Assembly.Load("DoSomeThing");//引用dll
Type type = assembly.GetType("DoSomeThing.Singleton");
Activator.CreateInstance(type, true);
Activator.CreateInstance(type, true);
Activator.CreateInstance(type, true);
Activator.CreateInstance(type, true);
结果
结果可以看到,即使是单例下的私有构造函数,也被调用了很多次
泛型构造函数调用
我们先创建一个泛型类
public class GenericClass<T,S>
{
public GenericClass()
{
Console.WriteLine("GenericClass");
}
}
调用
Console.WriteLine("********************创建泛型类对象**********************");
Assembly assembly = Assembly.Load("DoSomeThing");
Type type = assembly.GetType("DoSomeThing.GenericClass`2");
type = type.MakeGenericType(typeof(string),typeof(int));
Activator.CreateInstance(type);
结果
看结果是创建成功的,创建泛型类对象的时候,其实就是在创建类型的时候,在类型名称后面加上一个 `N 这个N就是代表有几个泛型参数,然后通过MakeGenericType进行添加泛型类型即可