说起反射,我们并不陌生,并且我在之前的博客中,http://blog.youkuaiyun.com/gaibian0823/article/details/44624423也已经提到过,一个是这里面提到的只是理解层面上的,二是反射一般很少自己出现,都是结合着其他知识点出现。所以这次不会再体现在理解层面上,我们从例子中看问题。
一、反射
反射就是在我们不去引用另外一个程序集或者模块,而直接调用他的属性、方法。
1.首先是这个程序,我要在Program中调用User中的属性以及方法。
2.类User中的代码:
<span style="font-family:KaiTi_GB2312;font-size:18px;">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ITOO_DAL
{
public class User
{
//字段
public string Field = "Hello World";
//属性
public string Name { get; set; }
//无参构造
public User()
{
this.Name = "无参构造";
}
//有参构造
public User(string UserName)
{
this.Name = UserName;
}
//public函数
public void publicFunction()
{
Console.WriteLine(string.Format("调用的是我public方法"));
}
//private函数
private void privateFunction()
{
Console.WriteLine(string.Format("调用的是我private方法"));
}
//static函数
public static void staticFunction()
{
Console.WriteLine(string.Format("调用的是我静态static方法"));
}
//public带参带返回值函数
public string publicFunctionPara(string UserName)
{
return string.Format("调用带参带返回值函数,参数为:{0}",UserName);
}
}
}
</span>
3.主函数
<span style="font-family:KaiTi_GB2312;font-size:18px;">using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace ITOO_Reflection
{
class Program
{
static void Main(string[] args)
{
//使用 Assembly 定义和加载程序集,
//加载在程序集清单中列出的模块,
//以及从此程序集中查找类型并创建该类型的实例.
//获取程序集
Assembly assembly = Assembly.Load("ITOO_DAL");
//从程序集中获取指定对象类型;
Type type = assembly.GetType("ITOO_DAL.User");
//方法一:创建类的实例
//使用Activator创建实例(无参数构造函数)
var userNoParameter = Activator.CreateInstance(type);
//使用Activator创建实例(带参数构造函数)
var userParameter = Activator.CreateInstance(type, "wangjinbo");
//方法二:创建类的实例
//使用无参构造函数创建类(先反射创建构造函数,再使用构造函数创建类)
ConstructorInfo constructorNoParameter = type.GetConstructor(new Type[] { });
var userNoParameterByConstructorInfo = constructorNoParameter.Invoke(new object[] { });
//使用有参构造函数创建类(先反射创建构造函数,再使用构造函数创建类)
ConstructorInfo constructorParameter = type.GetConstructor(new Type[] { typeof(string) });
var userParameterByConstructorInfo = constructorParameter.Invoke(new object[] { "wangjinbo" });
//调用public函数(无参数)
type.InvokeMember("publicFunction",
BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, userNoParameter,
null);
//调用public函数(带参数)
string returnValuePublic =
type.InvokeMember("publicFunctionPara",
BindingFlags.InvokeMethod | BindingFlags.OptionalParamBinding, null, userNoParameter,
new object[] { "wangjinbo" }) as string;
Console.WriteLine(returnValuePublic);
//调用静态方法
string returnValueStatic =
type.InvokeMember("staticFunction", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static,
null, null, new object[] { }) as string;
Console.WriteLine(returnValueStatic);
//反射属性
var Name =
type.InvokeMember("Name", BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance, null,
userNoParameter, new object[] { }) as string;
Console.WriteLine(Name);
//设置属性(设置Name属性为"NewName")
type.InvokeMember("Name", BindingFlags.SetProperty | BindingFlags.Public | BindingFlags.Instance, null,
userNoParameter, new object[] { "NewName" });
//反射字段
string Field =
type.InvokeMember("Field", BindingFlags.GetField | BindingFlags.Public | BindingFlags.Instance, null,
userNoParameter, new object[] { }) as string;
Console.WriteLine(Field);
//设置字段(设置Field字段为"NewField")
type.InvokeMember("Field", BindingFlags.SetField | BindingFlags.Public | BindingFlags.Instance, null,
userNoParameter, new object[] { "NewField" });
}
}
}
</span>
上面就是通过反射从一个类中调用了另一个类中的属性以及方法。
二、反射+IOC容器
1.什么是IOC?
IOC即控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题,也是轻量级的Spring框架的核心。 控制反转一般分为两种类型,依赖注入(Dependency Injection,简称DI)和依赖查找(Dependency Lookup)。依赖注入应用比较广泛。
当然这是官方解释,我的解释是:不创建对象,但是描述创建它们的方式。在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务。容器负责将这些联系在一起。简单的来讲,就是由容器控制程序之间的关系,而非传统实现中,由程序代码直接操控。这也就是所谓“控制反转”的概念所在:控制权由应用代码中转到了外部容器,控制权的转移,是所谓反转。
2.反射+依赖注入、依赖查找
首先,我们来看依赖注入:
配置文件中
通过get,set注入
然后直接使用D层所有方法:
2.依赖查找
配置文件中:
程序中,GetObject为反射:
依赖注入和依赖查找都用到了反射,但是依赖注入是被动的,依赖查找是主动的,依赖查找是需要来把配置文件中的id写进来,而注入get,set后,可以使用里面的所有方法。
总的流程就是:
1.加载配置文件中的所有内容。
2.将id,value放到一个哈希表中。
3.反射来查找id或者name,来调用相关类。
这些知识,我们用了很长时间,但是前面并不理解,所以我们需要更加主动地去整理总结这些知识,而不是被动地接受。