Castle IOC容器构建配置详解(二)

摘要:在前一篇文章中我们并没有考虑配置的组件参数是什么类型,也没有在配置文件中指定过类型,那么Castle IOC是如何进行类型转换的?如何配置一些复杂的数据类型?如果有自定义的类型如何去进行类型转换?本文将进行一一解答这些问题。
              
主要内容
1 .基本类型配置
2 Array类型配置
3 List类型配置
4 Dictionary类型配置
5 .自定义类型转换
 
一.基本类型配置
Castle IOC的配置文件中,大家可能都已经注意一个问题了,就是不管组件接收的是什么基本数据类型,我们一律没有在配置文件中指定,也就是说,不管组件接收的类型是int型或者是String类型,我们都可以这样去配置:
None.gif < component  id ="MyComponent" >
None.gif
None.gif    
< parameters >
None.gif
None.gif        
< port > 10 </ port >
None.gif
None.gif    
</ parameters >
None.gif
None.gif
</ 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的参数
None.gif //  出处: [url]http://terrylee.cnblogs.com[/url]
None.gif
public   class  MyComponent
ExpandedBlockStart.gif
{
InBlock.gif    
private int[] orders;
InBlock.gif
InBlock.gif    
public int[]Orders
ExpandedSubBlockStart.gif    
{
InBlock.gif
ExpandedSubBlockStart.gif        
getreturn this.orders;}
ExpandedSubBlockEnd.gif    }

InBlock.gif    
public MyComponent()
ExpandedSubBlockStart.gif    
{
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif    
public MyComponent(int[]orders)
ExpandedSubBlockStart.gif    
{
InBlock.gif        
this.orders = orders;
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}
这时候我们的配置文件可以如下去写
None.gif <!-- 出处:[url]http://terrylee.cnblogs.com[/url] -->
None.gif
None.gif
<? xml version="1.0" encoding="utf-8"  ?>
None.gif
None.gif
< configuration >
None.gif
None.gif    
< component  id ="e"  type ="CastleDemo.MyComponent,CastleDemo" >
None.gif
None.gif        
< parameters >
None.gif
None.gif            
< Orders >
None.gif
None.gif                
< item  type ="System.Int32" >
None.gif
None.gif                    
< item > 1 </ item >
None.gif
None.gif                    
< item > 2 </ item >
None.gif
None.gif                    
< item > 3 </ item >
None.gif
None.gif                
</ item >
None.gif
None.gif            
</ Orders >
None.gif
None.gif        
</ parameters >
None.gif
None.gif    
</ component >
None.gif
None.gif
</ configuration >
三.List类型配置
组件构造函数有一个IList类型的参数
None.gif // 出处: [url]http://terrylee.cnblogs.com[/url]
None.gif
public   class  MyComponent
ExpandedBlockStart.gif
{
InBlock.gif    
private IList _hosts;
InBlock.gif
InBlock.gif    
public MyComponent(IList hosts)
ExpandedSubBlockStart.gif    
{
InBlock.gif        
this._hosts = hosts;
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
public IList Hosts
ExpandedSubBlockStart.gif    
{
ExpandedSubBlockStart.gif        
get return _hosts; }
ExpandedSubBlockEnd.gif    }

InBlock.gif    
//dot.gifdot.gif
ExpandedBlockEnd.gif
}
这时候我们的配置文件应该如下
None.gif <!-- 出处:[url]http://terrylee.cnblogs.com[/url] -->
None.gif
None.gif
<? xml version="1.0" encoding="utf-8"  ?>
None.gif
None.gif
< configuration >
None.gif
None.gif    
< component  id ="mycomponent"  type ="CastleDemo.MyComponent,CastleDemo" >
None.gif
None.gif        
< parameters >
None.gif
None.gif            
< hosts >
None.gif
None.gif                
< list   type ="System.String" >
None.gif
None.gif                    
< item > server1 </ item >
None.gif
None.gif                    
< item > server2 </ item >
None.gif
None.gif                    
< item > server3 </ item >
None.gif
None.gif                    
< item > server4 </ item >
None.gif
None.gif                
</ list >
None.gif
None.gif            
</ hosts >
None.gif
None.gif        
</ parameters >
None.gif
None.gif    
</ component >
None.gif
None.gif
</ configuration >
四.Dictionary类型配置
组件构造函数有一个Idictionary类型的参数
None.gif // 出处: [url]http://terrylee.cnblogs.com[/url]
None.gif
public   class  MyComponent
ExpandedBlockStart.gif
{
InBlock.gif    
private IDictionary _dictionary;
InBlock.gif
InBlock.gif    
public MyComponent(IDictionary d)
ExpandedSubBlockStart.gif    
{
InBlock.gif        
this._dictionary = d;
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
public IDictionary Dictionary
ExpandedSubBlockStart.gif    
{
ExpandedSubBlockStart.gif        
getreturn this._dictionary;}
ExpandedSubBlockEnd.gif    }

InBlock.gif    
//dot.gifdot.gif
ExpandedBlockEnd.gif
}
配置文件应该如下去写:
None.gif <!-- 出处:[url]http://terrylee.cnblogs.com[/url] -->
None.gif
None.gif
<? xml version="1.0" encoding="utf-8"  ?>
None.gif
None.gif
< configuration >
None.gif
None.gif    
< component  id ="MyComponent"  type ="CastleDemo.MyComponent,CastleDemo" >
None.gif
None.gif        
< parameters >
None.gif
None.gif            
< d >
None.gif
None.gif                
< dictionary >
None.gif
None.gif                    
< entry  key ="a" > a </ entry >
None.gif
None.gif                    
< entry  key ="b" > b </ entry >
None.gif
None.gif                    
< entry  key ="c" > c </ entry >
None.gif
None.gif                
</ dictionary >
None.gif
None.gif            
</ d >
None.gif
None.gif        
</ parameters >
None.gif
None.gif    
</ component >
None.gif
None.gif
</ configuration >
或者我们可以在配置文件中分别指定 Key和 Value的数据类型,分别使用 keyType和 valueType。
None.gif <!-- 出处:[url]http://terrylee.cnblogs.com[/url] -->
None.gif
None.gif
<? xml version="1.0" encoding="utf-8"  ?>
None.gif
None.gif
< configuration >
None.gif
None.gif    
< component  id ="MyComponent"  type ="CastleDemo.MyComponent,CastleDemo" >
None.gif
None.gif        
< parameters >
None.gif
None.gif            
< d >
None.gif
None.gif                
< dictionary  keyType ="System.String, mscorlib"  valueType ="System.String, mscorlib" >
None.gif
None.gif                    
< entry  key ="a" > a </ entry >
None.gif
None.gif                    
< entry  key ="b" > b </ entry >
None.gif
None.gif                    
< entry  key ="c" > c </ entry >
None.gif
None.gif                
</ dictionary >
None.gif
None.gif            
</ d >
None.gif
None.gif        
</ parameters >
None.gif
None.gif    
</ component >
None.gif
None.gif
</ configuration >

五.自定义类型转换
要实现我们自定义的类型转换,在这之前我们还是花一点时间来看看Castle IOC中是如何实现类型的转换的。在SubSystems中有一个Conversion,专门负责类型的转换,通过一个类型转换器 ConversionManager 来实现对类型转换的管理,在DefaultConversionManager初始化的时候,会加载以下几个类型转换:
None.gif protected   virtual   void  InitDefaultConverters()
ExpandedBlockStart.gif
{
InBlock.gif    Add( 
new PrimitiveConverter() );
InBlock.gif
InBlock.gif    Add( 
new TypeNameConverter() );
InBlock.gif
InBlock.gif    Add( 
new EnumConverter() );
InBlock.gif
InBlock.gif    Add( 
new ListConverter() );
InBlock.gif
InBlock.gif    Add( 
new DictionaryConverter() );
InBlock.gif
InBlock.gif    Add( 
new ArrayConverter() ); 
InBlock.gif
ExpandedBlockEnd.gif}
这些类型转换器之间的结构图如下:
1
PrimitiveConverter :负责基本数据类型的转换
TypeNameConverter :负责把一个类型的名字转换成这个类型的实例
EnumConverter :负责枚举类型的转换
ListConverter :负责Ilist数据类型的转换
DictionaryConverter :负责Idictionary数据类型转换
ArrayConverter :负责Array数据类型转换
以其中的 PrimitiveConverter 为例来看一下它的实现代码:
None.gif public   class  PrimitiveConverter : AbstractTypeConverter
ExpandedBlockStart.gif
{
InBlock.gif    
private Type[] types;
InBlock.gif
InBlock.gif    
public PrimitiveConverter()
ExpandedSubBlockStart.gif    
{
InBlock.gif        types 
= new Type[]
InBlock.gif
ExpandedSubBlockStart.gif            
{
InBlock.gif                
typeof (Char),
InBlock.gif
InBlock.gif                
typeof (DateTime),
InBlock.gif
InBlock.gif                
typeof (Decimal),
InBlock.gif
InBlock.gif                
typeof (Boolean),
InBlock.gif
InBlock.gif                
typeof (Int16),
InBlock.gif
InBlock.gif                
typeof (Int32),
InBlock.gif
InBlock.gif                
typeof (Int64),
InBlock.gif
InBlock.gif                
typeof (UInt16),
InBlock.gif
InBlock.gif                
typeof (UInt32),
InBlock.gif
InBlock.gif                
typeof (UInt64),
InBlock.gif
InBlock.gif                
typeof (Byte),
InBlock.gif
InBlock.gif                
typeof (SByte),
InBlock.gif
InBlock.gif                
typeof (Single),
InBlock.gif
InBlock.gif                
typeof (Double),
InBlock.gif
InBlock.gif                
typeof (String)
InBlock.gif
ExpandedSubBlockEnd.gif            }
;
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
public override bool CanHandleType(Type type)
ExpandedSubBlockStart.gif    
{
InBlock.gif        
return Array.IndexOf(types, type) != -1;
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
public override object PerformConversion(String value, Type targetType)
ExpandedSubBlockStart.gif    
{
InBlock.gif        
if (targetType == typeof(String)) return value;
InBlock.gif
InBlock.gif        
try
ExpandedSubBlockStart.gif        
{
InBlock.gif            
return Convert.ChangeType(value, targetType);
InBlock.gif
ExpandedSubBlockEnd.gif        }

InBlock.gif        
catch(Exception ex)
ExpandedSubBlockStart.gif        
{
InBlock.gif            String message 
= String.Format(
InBlock.gif
InBlock.gif                
"Could not convert from '{0}' to {1}"
InBlock.gif
InBlock.gif                value, targetType.FullName);
InBlock.gif
InBlock.gif            
throw new ConverterException(message, ex);
InBlock.gif
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
public override object PerformConversion(IConfiguration configuration, Type targetType)
InBlock.gif
ExpandedSubBlockStart.gif    
{
InBlock.gif
InBlock.gif        
return PerformConversion(configuration.Value, targetType);
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedBlockEnd.gif}
可以看到, Castle IOC会把所有的配置参数都当作 String类型接收,如果目标类型是 String,则直接返回结果,否则再进行类型转换。由此我们可以分析得出,要实现自己的类型转换,有以下两步:
1 .编写的自己的类型转换类,实现接口ITypeConverter
None.gif // 出处: [url]http://terrylee.cnblogs.com[/url]
None.gif
public   class  MyTypeConverter : ITypeConverter
ExpandedBlockStart.gif
{
InBlock.gif    
//dot.gifdot.gif
ExpandedBlockEnd.gif
}
2 .添加自己的类型转换到 ConversionManager
None.gif IKernel kernel  =   new  DefaultKernel();
None.gif
None.gifIConversionManager conversionMng 
=  (IConversionManager) 
None.gif
None.gif    kernel.GetSubSystem( SubSystemConstants.ConversionManagerKey );
None.gif
None.gifconversionMng.Add(
new  MyTypeConverter());
 
关于Castle IOC容器中构建配置信息就到这里了,我总共分为了一,二两部分来讲解。Castle IOC系列的文章后续还有很多,希望大家继续关注!










本文转自lihuijun51CTO博客,原文链接: http://blog.51cto.com/terrylee/67678  ,如需转载请自行联系原作者

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值