摘要:在前一篇文章中我们并没有考虑配置的组件参数是什么类型,也没有在配置文件中指定过类型,那么Castle IOC是如何进行类型转换的?如何配置一些复杂的数据类型?如果有自定义的类型如何去进行类型转换?本文将进行一一解答这些问题。
主要内容
1.基本类型配置
2.Array类型配置
3.List类型配置
4.Dictionary类型配置
5.自定义类型转换
一.基本类型配置
在Castle IOC的配置文件中,大家可能都已经注意一个问题了,就是不管组件接收的是什么基本数据类型,我们一律没有在配置文件中指定,也就是说,不管组件接收的类型是int型或者是String类型,我们都可以这样去配置:
<component id="MyComponent">

<parameters>

<port>10</port>

</parameters>

</component>
这是因为在Castle IOC中,MicroKernel中的SubSystem中有一个TypeConverter,它专门负责类型的转换。参数的注入一般都是通过构造函数或者公有的属性,基本数据类型在配置文件我们不需要用专门的节点去配置,但是对于一些复杂的数据类型久有些不一样。目前Castle IOC能够支持的数据类型如下。
|
类型
|
节点
|
示例
|
|
System.Int32, Int16, Int64
|
-
|
<parameters>
<port>10</port>
</parameters>
|
|
System.UInt32, UInt16, UInt64
|
-
|
<parameters>
<port>10</port>
</parameters>
|
|
System.Char
|
-
|
<parameters>
<letter>a</letter>
</parameters>
|
|
System.Single, Double, Decimal
|
-
|
<parameters>
<threshold>13.22</threshold>
</parameters>
|
|
System.String
|
-
|
<parameters>
<server>mail.host.com</server>
</parameters>
|
|
System.Byte, SByte
|
-
|
<parameters>
<rcolor>144</rcolor>
</parameters>
|
|
System.Boolean
|
-
|
<parameters>
<enabled>0</enabled>
</parameters>
|
|
System.DateTime
|
-
|
<parameters>
<initial>11022005</initial>
</parameters>
|
|
System.Type
|
-
|
<parameters>
<type>Components.MyComponent, Components</type>
</parameters>
|
|
System.Array
|
array
|
参见后面
|
|
System.Collections.IList
|
list
|
参见后面
|
|
System.Collections.IDictionary
|
dictionary
|
参见后面
|
如果有其它的类型,我们需要编写自定义的TypeConverter。
二.Array类型配置
组件构造函数有一个Array的参数
// 出处:http://terrylee.cnblogs.com
public class MyComponent


{
private int[] orders;

public int[]Orders

{


get
{ return this.orders;}
}
public MyComponent()

{

}
public MyComponent(int[]orders)

{
this.orders = orders;
}
}
这时候我们的配置文件可以如下去写
<!--出处:http://terrylee.cnblogs.com-->

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

<component id="e" type="CastleDemo.MyComponent,CastleDemo">

<parameters>

<Orders>

<item type="System.Int32">

<item>1</item>

<item>2</item>

<item>3</item>

</item>

</Orders>

</parameters>

</component>

</configuration>
三.List类型配置
组件构造函数有一个IList类型的参数
//出处:http://terrylee.cnblogs.com
public class MyComponent


{
private IList _hosts;

public MyComponent(IList hosts)

{
this._hosts = hosts;
}

public IList Hosts

{

get
{ return _hosts; }
}
//

}
这时候我们的配置文件应该如下
<!--出处:http://terrylee.cnblogs.com-->

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

<component id="mycomponent" type="CastleDemo.MyComponent,CastleDemo">

<parameters>

<hosts>

<list type="System.String">

<item>server1</item>

<item>server2</item>

<item>server3</item>

<item>server4</item>

</list>

</hosts>

</parameters>

</component>

</configuration>
四.Dictionary类型配置
组件构造函数有一个Idictionary类型的参数
//出处:http://terrylee.cnblogs.com
public class MyComponent


{
private IDictionary _dictionary;

public MyComponent(IDictionary d)

{
this._dictionary = d;
}

public IDictionary Dictionary

{

get
{ return this._dictionary;}
}
//

}
配置文件应该如下去写:
<!--出处:http://terrylee.cnblogs.com-->

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

<component id="MyComponent" type="CastleDemo.MyComponent,CastleDemo">

<parameters>

<d>

<dictionary>

<entry key="a">a</entry>

<entry key="b">b</entry>

<entry key="c">c</entry>

</dictionary>

</d>

</parameters>

</component>

</configuration>
或者我们可以在配置文件中分别指定Key和Value的数据类型,分别使用keyType和valueType。
<!--出处:http://terrylee.cnblogs.com-->

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

<component id="MyComponent" type="CastleDemo.MyComponent,CastleDemo">

<parameters>

<d>

<dictionary keyType="System.String, mscorlib" valueType="System.String, mscorlib">

<entry key="a">a</entry>

<entry key="b">b</entry>

<entry key="c">c</entry>

</dictionary>

</d>

</parameters>

</component>

</configuration>
五.自定义类型转换
要实现我们自定义的类型转换,在这之前我们还是花一点时间来看看Castle IOC中是如何实现类型的转换的。在SubSystems中有一个Conversion,专门负责类型的转换,通过一个类型转换器ConversionManager来实现对类型转换的管理,在DefaultConversionManager初始化的时候,会加载以下几个类型转换:
protected virtual void InitDefaultConverters()


{
Add( new PrimitiveConverter() );

Add( new TypeNameConverter() );

Add( new EnumConverter() );

Add( new ListConverter() );

Add( new DictionaryConverter() );

Add( new ArrayConverter() );

}
这些类型转换器之间的结构图如下:

图1
PrimitiveConverter:负责基本数据类型的转换
TypeNameConverter:负责把一个类型的名字转换成这个类型的实例
EnumConverter:负责枚举类型的转换
ListConverter:负责Ilist数据类型的转换
DictionaryConverter:负责Idictionary数据类型转换
ArrayConverter:负责Array数据类型转换
以其中的PrimitiveConverter为例来看一下它的实现代码:
public class PrimitiveConverter : AbstractTypeConverter


{
private Type[] types;

public PrimitiveConverter()

{
types = new Type[]


{
typeof (Char),

typeof (DateTime),

typeof (Decimal),

typeof (Boolean),

typeof (Int16),

typeof (Int32),

typeof (Int64),

typeof (UInt16),

typeof (UInt32),

typeof (UInt64),

typeof (Byte),

typeof (SByte),

typeof (Single),

typeof (Double),

typeof (String)

};
}

public override bool CanHandleType(Type type)

{
return Array.IndexOf(types, type) != -1;
}

public override object PerformConversion(String value, Type targetType)

{
if (targetType == typeof(String)) return value;

try
