摘要:在前一篇文章中我们并没有考虑配置的组件参数是什么类型,也没有在配置文件中指定过类型,那么Castle IOC是如何进行类型转换的?如何配置一些复杂的数据类型?如果有自定义的类型如何去进行类型转换?本文将进行一一解答这些问题。
主要内容
1
.基本类型配置
2
.Array类型配置
3
.List类型配置
4
.Dictionary类型配置
5
.自定义类型转换
一.基本类型配置
在Castle IOC的配置文件中,大家可能都已经注意一个问题了,就是不管组件接收的是什么基本数据类型,我们一律没有在配置文件中指定,也就是说,不管组件接收的类型是int型或者是String类型,我们都可以这样去配置:
<
component
id
="MyComponent"
>
< parameters >
< port > 10 </ port >
</ parameters >
</ component >
< 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的参数
//
出处:
[url]http://terrylee.cnblogs.com[/url]
public class MyComponent
{
private int[] orders;
public int[]Orders
{
get{ return this.orders;}
}
public MyComponent()
{
}
public MyComponent(int[]orders)
{
this.orders = orders;
}
}
public class MyComponent
{
private int[] orders;
public int[]Orders
{
get{ return this.orders;}
}
public MyComponent()
{
}
public MyComponent(int[]orders)
{
this.orders = orders;
}
}
这时候我们的配置文件可以如下去写
<!--
出处:[url]http://terrylee.cnblogs.com[/url]
-->
<? 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 >
<? 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类型的参数
//
出处:
[url]http://terrylee.cnblogs.com[/url]
public class MyComponent
{
private IList _hosts;
public MyComponent(IList hosts)
{
this._hosts = hosts;
}
public IList Hosts
{
get { return _hosts; }
}
//
}
public class MyComponent
{
private IList _hosts;
public MyComponent(IList hosts)
{
this._hosts = hosts;
}
public IList Hosts
{
get { return _hosts; }
}
//
}
这时候我们的配置文件应该如下
<!--
出处:[url]http://terrylee.cnblogs.com[/url]
-->
<? 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 >
<? 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类型的参数
//
出处:
[url]http://terrylee.cnblogs.com[/url]
public class MyComponent
{
private IDictionary _dictionary;
public MyComponent(IDictionary d)
{
this._dictionary = d;
}
public IDictionary Dictionary
{
get{ return this._dictionary;}
}
//
}
public class MyComponent
{
private IDictionary _dictionary;
public MyComponent(IDictionary d)
{
this._dictionary = d;
}
public IDictionary Dictionary
{
get{ return this._dictionary;}
}
//
}
配置文件应该如下去写:
<!--
出处:[url]http://terrylee.cnblogs.com[/url]
-->
<? 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 >
<? 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。
<!--
出处:[url]http://terrylee.cnblogs.com[/url]
-->
<? 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 >
<? 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() );
}
{
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
{
return Convert.ChangeType(value, targetType);
}
catch(Exception ex)
{
String message = String.Format(
"Could not convert from '{0}' to {1}",
value, targetType.FullName);
throw new ConverterException(message, ex);
}
}
public override object PerformConversion(IConfiguration configuration, Type targetType)
{
return PerformConversion(configuration.Value, targetType);
}
}
{
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
{
return Convert.ChangeType(value, targetType);
}
catch(Exception ex)
{
String message = String.Format(
"Could not convert from '{0}' to {1}",
value, targetType.FullName);
throw new ConverterException(message, ex);
}
}
public override object PerformConversion(IConfiguration configuration, Type targetType)
{
return PerformConversion(configuration.Value, targetType);
}
}
可以看到,
Castle IOC会把所有的配置参数都当作
String类型接收,如果目标类型是
String,则直接返回结果,否则再进行类型转换。由此我们可以分析得出,要实现自己的类型转换,有以下两步:
1
.编写的自己的类型转换类,实现接口ITypeConverter
//
出处:
[url]http://terrylee.cnblogs.com[/url]
public class MyTypeConverter : ITypeConverter
{
//
}
public class MyTypeConverter : ITypeConverter
{
//
}
2
.添加自己的类型转换到
ConversionManager
中
IKernel kernel
=
new
DefaultKernel();
IConversionManager conversionMng = (IConversionManager)
kernel.GetSubSystem( SubSystemConstants.ConversionManagerKey );
conversionMng.Add( new MyTypeConverter());
IConversionManager conversionMng = (IConversionManager)
kernel.GetSubSystem( SubSystemConstants.ConversionManagerKey );
conversionMng.Add( new MyTypeConverter());
关于Castle IOC容器中构建配置信息就到这里了,我总共分为了一,二两部分来讲解。Castle IOC系列的文章后续还有很多,希望大家继续关注!
本文转自lihuijun51CTO博客,原文链接:
http://blog.51cto.com/terrylee/67678
,如需转载请自行联系原作者