十年前的我雄心勃勃,那时候刚从N软离职,在卡离职的20几天闭关决心写一套框架。虽然后面没实用,不过后续的框架借鉴了很多当时的经验和设计。
面向对象的三大特性是:
1.封装
2.继承
3.多态
C#作为面向对象语言。同时也是高级语言,如果不能把面向对象的特性用起来,那么是浪费的。在我看来没有多态的程序是没有灵魂的。多态借助接口实现,但是直接在接口对象后面new实现对象实际是没实现多态的。如下:
IStudent stu=new Student();
上面这种代码其实不是面向接口编程,因为改Student实现类还得改new代码编译。达不到多态的效果。为了实现多态就需要借助设计模式的工程模式。借助C#的反射按配置反射得到实现对象赋值给接口对象。即实现类可配置,后期我实现的各个程序都是按面向接口可配置实现的。在N软离职空窗期我构想实现一套框架体系,名为“GreenFram”。代码如下:
Green源码
框架包含“依赖注入”,“AOP面向切面”,“数据访问层”,“公共层”。首先需要使用IOC依赖注入功能探索。
通过解析Xml配置后用C#反射实现容器
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Reflection;
namespace MyselfIocTest
{
public class MyXmlFactory
{
private IDictionary<string, object> objList = new Dictionary<string, object>();
public MyXmlFactory(string xmlFileName)
{
InitObjects(xmlFileName);//实例Ioc容器
DiObject(xmlFileName);//属性注入
}
/// <summary>
/// 实例Ioc容器
/// </summary>
/// <param name="xmlFileName">配置文件路径名</param>
private void InitObjects(string xmlFileName)
{
XElement root = XElement.Load(xmlFileName);
var objects = from obj in root.Elements("object") select obj;
//无参构造函数
objList = objects.Where(obj=>obj.Element("constructor-arg") == null).ToDictionary(
k => k.Attribute("id").Value
,v => { string typeName = v.Attribute("type").Value
; Type type = Type.GetType(typeName)
; return Activator.CreateInstance(type); }
);
//有参构造函数
foreach(XElement elem in objects.Where(obj=>obj.Element("constructor-arg")!=null))
{
string id = elem.Attribute("id").Value;
string typeName = elem.Attribute("type").Value;
Type type = Type.GetType(typeName);
var args = from property in type.GetConstructors()[0].GetParameters()
join e1 in elem.Elements("constructor-arg")
on property.Name equals e1.Attribute("name").Value
select Convert.ChangeType(e1.Attribute("value").Value, property.ParameterType);
object obj = Activator.CreateInstance(type, args.ToArray());
objList.Add(id, obj);
}
}
/// <summary>
/// 属性注入
/// </summary>
private void DiObject(string fileName)
{
XElement root = XElement.Load(fileName);
var objects = from obj in root.Elements("object") select obj;
foreach (KeyValuePair<string, object> item in objList)
{
foreach (var e1 in objects.Where(e => e.Attribute("id").Value == item.Key).Elements("property"))
{
Type type = item.Value.GetType();
foreach (PropertyInfo property in type.GetProperties())
{
if (property.Name == e1.Attribute("name").Value)
{
if (e1.Attribute("value") != null)
{
if (e1.Attribute("value").Value == "")
{
Console.WriteLine("警告:"+e1.Attribute("name").Value + "的属性值为空");
}
property.SetValue(item.Value, Convert.ChangeType(e1.Attribute("value").Value, property.PropertyType), null);
}
else if (e1.Attribute("ref") != null)
{
object refObject = null;
if (objList.ContainsKey(e1.Attribute("ref").Value))
{
refObject = objList[e1.Attribute("ref").Value];
}
else
{
Console.WriteLine(e1.Attribute("name").Value + "没有参照对象,请确定已注册");
}
property.SetValue(item.Value, refObject, null);
}
}
}
}
}
}
/// <summary>
/// 获得对象
/// </summary>
/// <param name="objName">对象标示名</param>
/// <returns></returns>
public object GetObject(string objName)
{
object obj = null;
if (objList.ContainsKey(objName))
{
obj = objList[objName];
}
return obj;
}
}
}
配置对象
<?xml version="1.0" encoding="utf-8"?>
<objects >
<object id="Student" type="MyselfIocTest.Student">
<!--构造器注入-->
<constructor-arg name="name" value="张联珠"></constructor-arg>
<property name="MyTeacher" ref="Teacher"></property>
</object>
<object id="Teacher" type="MyselfIocTest.Teacher">
<!--构造器注入-->
<constructor-arg name="name" value="张三"></constructor-arg>
</object>
</objects>
使用容器代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MyselfIocTest
{
class Program
{
static void Main(string[] args)
{
MyXmlFactory myXmlFactory = new MyXmlFactory("myConfig.xml");
Student student = (Student)myXmlFactory.GetObject("Student");
Teacher t = (Teacher)myXmlFactory.GetObject("Teacher");
t.Say();
if (student != null)
{
student.Say();
}
Console.Read();
}
}
}
简单IOC
这样就可以通过配置得到对象实现new解耦,达到依赖注入。