之前我们学习里一个简易的IoC框架。今天我们接着上次的程序,实现带参数构造函数对象的实例和属性的注入 。原文地址:/GoodHelper/archive//11/02/SpringNet_MyDi.html
我感觉这个很有必要对应IOC框架的理解,知道注入的工作原理,对应实际的应用是很有帮助的。
我们知道可以通过反射获取类的构造函数及参数(GetConstructors方法);可以获取属性和属性的类型(GetProperties方法)。通过Activator的CreateInstance(Type type, params object[] args)方法可以创建带参数构造函数的实例。通过SetValue方法可以给属性赋值,这样一来,我们就上次的代码稍加改造就可以实现属性的注入了。
下面是完成的代码:
publicclassPerson
{
publicstringName{get;set;}
publicintAge{get;set;}
}
publicclassPersonDao
{
privateintintProp;
publicPersonDao(intintProp)
{
this.intProp=intProp;
}
publicPersonEntity{get;set;}
publicoverridestringToString()
{
return"构造函数参数intProp为:"+this.intProp;
}
}
publicclassObjectFactory
{
privateIDictionary<string,object>objectDefine=newDictionary<string,object>();
privateObjectFactory(stringfileName)
{
InstanceObjects(fileName);//实例IoC容器
DiObjects(fileName);//属性注入
}
privatestaticObjectFactoryinstance;
privatestaticobjectlockHelper=newobject();
publicstaticObjectFactoryInstance(stringfileName)
{
if(instance==null)
{
lock(lockHelper)
{
instance=instance??newObjectFactory(fileName);
}
}
returninstance;
}
///<summary>
///实例IoC容器
///</summary>
///<paramname="fileName"></param>
privatevoidInstanceObjects(stringfileName)
{
XElementroot=XElement.Load(fileName);
varobjects=fromobjinroot.Elements("object")
selectobj;
//无参构造函数
objectDefine=objects.Where(obj=>
obj.Element("constructor-arg")==null).ToDictionary(
k=>k.Attribute("id").Value,
v=>
{
stringtypeName=v.Attribute("type").Value;
Typetype=Type.GetType(typeName);
returnActivator.CreateInstance(type);
}
);
//有参构造函数
foreach(XElementiteminobjects.Where(obj=>
obj.Element("constructor-arg")!=null))
{
stringid=item.Attribute("id").Value;
stringtypeName=item.Attribute("type").Value;
Typetype=Type.GetType(typeName);
varargs=frompropertyintype.GetConstructors()[0].GetParameters()
joinelinitem.Elements("constructor-arg")
onproperty.Nameequalsel.Attribute("name").Value
selectConvert.ChangeType(el.Attribute("value").Value,
property.ParameterType);
objectobj=Activator.CreateInstance(type,args.ToArray());
objectDefine.Add(id,obj);
}
}
///<summary>
///属性注入
///</summary>
///<paramname="fileName"></param>
privatevoidDiObjects(stringfileName)
{
XElementroot=XElement.Load(fileName);
varobjects=fromobjinroot.Elements("object")
selectobj;
foreach(KeyValuePair<string,object>iteminobjectDefine)
{
foreach(varelinobjects.Where(e=>
e.Attribute("id").Value==item.Key).Elements("property"))
{
Typetype=item.Value.GetType();
//获取属性
foreach(PropertyInfopropertyintype.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);
}
elseif(el.Attribute("ref")!=null)
{
objectrefObject=null;
if(objectDefine.ContainsKey(el.Attribute("ref").Value))
{
refObject=objectDefine[el.Attribute("ref").Value];
}
//设置关联对象属性
property.SetValue(item.Value,refObject,null);
}
}
}
}
}
}
///<summary>
///获取对象
///</summary>
///<paramname="id"></param>
///<returns></returns>
publicobjectGetObject(stringid)
{
objectresult=null;
if(objectDefine.ContainsKey(id))
{
result=objectDefine[id];
}
returnresult;
}
} <?xmlversion="1.0"encoding="utf-8"?>
<objects>
<objectid="person"type="SpringNetMyDi.Person,SpringNetMyDi">
<!--属性值类型注入-->
<propertyname="Name"value="LiuDong"/>
<propertyname="Age"value="27"/>
</object>
<objectid="personDao"type="SpringNetMyDi.PersonDao,SpringNetMyDi">
<!--构造器注入-->
<constructor-argname="intProp"value="1"/>
<propertyname="Entity"ref="person"/>
</object>
</objects> classProgram
{
staticvoidMain(string[]args)
{
ObjectFactoryfactory=ObjectFactory.Instance(@"F:\Exercise\SpringNet\Step1\SpringNet_Lesson9\SpringNetMyDi\Objects.xml");
PersonDaodao=(PersonDao)factory.GetObject("personDao");
Console.WriteLine("姓名:"+dao.Entity.Name);
Console.WriteLine("年龄:"+dao.Entity.Age);
Console.WriteLine(dao);
Console.ReadLine();
}
}