基于配置文件和.NET反射机制实现IOC
(相关的DLL参考上篇的代码)
一 配置文件app.config
<?
xml version
=
"
1.0
"
encoding
=
"
utf-8
"
?>
< configuration >
< configSections >
< sectionGroup name = " Ioc " >
< section name = " objects1 " type = " Ioc.ConfigHandler, Ioc " />
</ sectionGroup >
</ configSections >
< Ioc >
< objects1 >
< object name = " SayHello " assembly = " HelloType.dll " typeName = " Ioc.EnglishHello " >
</ object >
< object name = " GenerateHello " assembly = " GenerateHello.dll " typeName = " Ioc.GenerateHello " >
< property id = " Param " value = " cn " ></ property >
</ object >
</ objects1 >
</ Ioc >
</ configuration >
< configuration >
< configSections >
< sectionGroup name = " Ioc " >
< section name = " objects1 " type = " Ioc.ConfigHandler, Ioc " />
</ sectionGroup >
</ configSections >
< Ioc >
< objects1 >
< object name = " SayHello " assembly = " HelloType.dll " typeName = " Ioc.EnglishHello " >
</ object >
< object name = " GenerateHello " assembly = " GenerateHello.dll " typeName = " Ioc.GenerateHello " >
< property id = " Param " value = " cn " ></ property >
</ object >
</ objects1 >
</ Ioc >
</ configuration >
二 处理XML节点的类:ConfigHandler
using
System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Configuration;
namespace Ioc
... {
class ConfigHandler : IConfigurationSectionHandler
...{
public object Create(object parent, object configContext, System.Xml.XmlNode section)
...{
ObjectInfo info;
PropertyInfo propInfo;
ConfigInfo cfgInfo = new ConfigInfo();
foreach (XmlNode node in section.ChildNodes)
...{
info = new ObjectInfo();
info.name = node.Attributes["name"].Value;
info.assemblyName = node.Attributes["assembly"].Value;
info.typeName = node.Attributes["typeName"].Value;
foreach (XmlNode prop in node)
...{
propInfo = new PropertyInfo();
propInfo.id = prop.Attributes["id"].Value;
propInfo.value = prop.Attributes["value"].Value;
info.properties.Add(propInfo);
}
cfgInfo.Objects.Add(info);
}
return cfgInfo;
}
}
}
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Configuration;
namespace Ioc
... {
class ConfigHandler : IConfigurationSectionHandler
...{
public object Create(object parent, object configContext, System.Xml.XmlNode section)
...{
ObjectInfo info;
PropertyInfo propInfo;
ConfigInfo cfgInfo = new ConfigInfo();
foreach (XmlNode node in section.ChildNodes)
...{
info = new ObjectInfo();
info.name = node.Attributes["name"].Value;
info.assemblyName = node.Attributes["assembly"].Value;
info.typeName = node.Attributes["typeName"].Value;
foreach (XmlNode prop in node)
...{
propInfo = new PropertyInfo();
propInfo.id = prop.Attributes["id"].Value;
propInfo.value = prop.Attributes["value"].Value;
info.properties.Add(propInfo);
}
cfgInfo.Objects.Add(info);
}
return cfgInfo;
}
}
}
三 与object节点对应的类:ConfigInfo
using
System;
using System.Collections;
using System.Text;
namespace Ioc
... {
internal class ConfigInfo
...{
public ArrayList Objects = new ArrayList();
public ObjectInfo FindByName(string name)
...{
foreach (ObjectInfo o in Objects)
...{
if (o.name == name)
return o;
}
return null;
}
}
internal class ObjectInfo
...{
public string name;
public string assemblyName;
public string typeName;
public ArrayList properties = new ArrayList();
}
internal class PropertyInfo
...{
public string id;
public string value;
}
}
using System.Collections;
using System.Text;
namespace Ioc
... {
internal class ConfigInfo
...{
public ArrayList Objects = new ArrayList();
public ObjectInfo FindByName(string name)
...{
foreach (ObjectInfo o in Objects)
...{
if (o.name == name)
return o;
}
return null;
}
}
internal class ObjectInfo
...{
public string name;
public string assemblyName;
public string typeName;
public ArrayList properties = new ArrayList();
}
internal class PropertyInfo
...{
public string id;
public string value;
}
}
四 动态生成对象的类:SayHelloFactory
using
System;
using System.IO;
using System.Configuration;
using System.Reflection;
namespace Ioc
... {
class SayHelloFactory
...{
public static object Create(string name)
...{
ConstructorInfo studentConstructor2 = null;
Assembly assembly;
object o = null;
object p;
string rootPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) +
Path.DirectorySeparatorChar;
//<sectionGroup name="Ioc">
ConfigInfo cfgInfo = (ConfigInfo)ConfigurationManager.GetSection("Ioc/objects1");
ObjectInfo info = cfgInfo.FindByName(name);
if (info != null)
...{
assembly = Assembly.LoadFile(rootPath + info.assemblyName);
//o = assembly.CreateInstance(info.typeName);
//Type t = o.GetType();
Type classSampleType = assembly.GetType(info.typeName);
studentConstructor2 = classSampleType.GetConstructor(new Type[] ...{ typeof(string) });
object[] args = new object[info.properties.Count];
for (int i = 0; i < info.properties.Count; i++)
...{
PropertyInfo prop = (PropertyInfo)info.properties[i];
args[i] = prop.value;
}
o = studentConstructor2.Invoke(args);
}
return o;
}
}
}
using System.IO;
using System.Configuration;
using System.Reflection;
namespace Ioc
... {
class SayHelloFactory
...{
public static object Create(string name)
...{
ConstructorInfo studentConstructor2 = null;
Assembly assembly;
object o = null;
object p;
string rootPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) +
Path.DirectorySeparatorChar;
//<sectionGroup name="Ioc">
ConfigInfo cfgInfo = (ConfigInfo)ConfigurationManager.GetSection("Ioc/objects1");
ObjectInfo info = cfgInfo.FindByName(name);
if (info != null)
...{
assembly = Assembly.LoadFile(rootPath + info.assemblyName);
//o = assembly.CreateInstance(info.typeName);
//Type t = o.GetType();
Type classSampleType = assembly.GetType(info.typeName);
studentConstructor2 = classSampleType.GetConstructor(new Type[] ...{ typeof(string) });
object[] args = new object[info.properties.Count];
for (int i = 0; i < info.properties.Count; i++)
...{
PropertyInfo prop = (PropertyInfo)info.properties[i];
args[i] = prop.value;
}
o = studentConstructor2.Invoke(args);
}
return o;
}
}
}
五 Main类:
using
System;
using System.Collections.Generic;
using System.Text;
namespace Ioc
... {
class Program
...{
static void Main(string[] args)
...{
try
...{
GenerateHello genHello = (GenerateHello)SayHelloFactory.Create("GenerateHello");
if (genHello != null)
genHello.Generate("Somebody");
}
catch (Exception ex)
...{
Console.WriteLine("Got an Error!" + ex.Message);
}
finally
...{
Console.Read();
}
}
}
}
using System.Collections.Generic;
using System.Text;
namespace Ioc
... {
class Program
...{
static void Main(string[] args)
...{
try
...{
GenerateHello genHello = (GenerateHello)SayHelloFactory.Create("GenerateHello");
if (genHello != null)
genHello.Generate("Somebody");
}
catch (Exception ex)
...{
Console.WriteLine("Got an Error!" + ex.Message);
}
finally
...{
Console.Read();
}
}
}
}
六 调试
程序会根据配置,来输出不同的结果。
当<property id="Param" value="cn"></property>时,输出中文
当<property id="Param" value="en"></property>时,输出英文
代码的具体分析,参考http://www.cnblogs.com/zhenyulu/articles/233968.html。我也是看了这篇文章之后,自己动手再写一下。
备注:
在app.config中有点要注意, <section name="objects1" type="Ioc.ConfigHandler, Ioc" />的name="objects1" 必须与下面节点的<objects1>一致