本文是对《一个简易的IoC框架》的延伸,实现带参数构造函数对象的实例和属性的注入 。
我们知道可以通过反射获取类的构造函数及参数(GetConstructors方法);可以获取属性和属性的类型(GetProperties方法)。通过Activator的CreateInstance(Type type, params object[] args)方法可以创建带参数构造函数的实例。通过SetValue方法可以给属性赋值,这样一来,我们就上次的代码稍加改造就可以实现属性的注入了。
下面是完成的代码:
- public class Person
- {
- public string Name { get; set; }
- public int Age { get; set; }
- }
C#代码
- public class PersonDao
- {
- private int intProp;
-
- public PersonDao(int intProp)
- {
- this.intProp = intProp;
- }
-
- public Person Entity { get; set; }
-
- public override string ToString()
- {
- return "构造函数参数intProp为:" + this.intProp;
- }
- }
C#代码
- public class ObjectFactory
- {
- private IDictionary<string, object> objectDefine = new Dictionary<string, object>();
-
- private ObjectFactory(string fileName)
- {
- InstanceObjects(fileName);
- DiObjects(fileName);
- }
-
- private static ObjectFactory instance;
-
- private static object lockHelper = new object();
-
- public static ObjectFactory Instance(string fileName)
- {
- if (instance == null)
- {
- lock (lockHelper)
- {
- instance = instance ?? new ObjectFactory(fileName);
- }
- }
- return instance;
- }
-
-
-
-
-
- private void InstanceObjects(string fileName)
- {
- XElement root = XElement.Load(fileName);
- var objects = from obj in root.Elements("object")
- select obj;
-
-
- objectDefine = 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 item in objects.Where(obj =>
- obj.Element("constructor-arg") != null))
- {
- string id = item.Attribute("id").Value;
- string typeName = item.Attribute("type").Value;
- Type type = Type.GetType(typeName);
- var args = from property in type.GetConstructors()[0].GetParameters()
- join el in item.Elements("constructor-arg")
- on property.Name equals el.Attribute("name").Value
- select Convert.ChangeType(el.Attribute("value").Value,
- property.ParameterType);
- object obj = Activator.CreateInstance(type, args.ToArray());
- objectDefine.Add(id, obj);
- }
- }
-
-
-
-
-
- private void DiObjects(string fileName)
- {
- XElement root = XElement.Load(fileName);
- var objects = from obj in root.Elements("object")
- select obj;
-
- foreach (KeyValuePair<string,object> item in objectDefine)
- {
- foreach (var el 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 == el.Attribute("name").Value)
- {
- if (el.Attribute("value") != null)
- {
-
- property.SetValue(item.Value,
- Convert.ChangeType(el.Attribute("value").Value,
- property.PropertyType), null);
- }
- else if (el.Attribute("ref") != null)
- {
- object refObject = null;
-
- if (objectDefine.ContainsKey(el.Attribute("ref").Value))
- {
- refObject = objectDefine[el.Attribute("ref").Value];
- }
-
- property.SetValue(item.Value, refObject, null);
- }
- }
- }
- }
- }
- }
-
-
-
-
-
-
- public object GetObject(string id)
- {
- object result = null;
-
- if (objectDefine.ContainsKey(id))
- {
- result = objectDefine[id];
- }
-
- return result;
- }
- }
XML/HTML代码
- <?xml version="1.0" encoding="utf-8" ?>
-
- <objects>
-
- <object id="person" type="SpringNetMyDi.Person, SpringNetMyDi">
-
- <property name="Name" value="lywill"/>
- <property name="Age" value="29"/>
-
- </object>
-
- <object id="personDao" type="SpringNetMyDi.PersonDao, SpringNetMyDi">
-
- <constructor-arg name="intProp" value="1"/>
-
- <property name="Entity" ref="person" />
-
- </object>
-
- </objects>
C#代码
- class Program
- {
- static void Main(string[] args)
- {
- ObjectFactory factory = ObjectFactory.Instance(@"D:\我的文档\桌面\springnetalldemo1\SpringNet_Lesson9\SpringNetMyDi\Objects.xml");
-
- PersonDao dao = (PersonDao)factory.GetObject("personDao");
-
- Console.WriteLine("姓名:" + dao.Entity.Name);
- Console.WriteLine("年龄:" + dao.Entity.Age);
- Console.WriteLine(dao);
-
- Console.ReadLine();
- }
- }
输入结果: