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

摘要:在前一篇文章中我们并没有考虑配置的组件参数是什么类型,也没有在配置文件中指定过类型,那么Castle IOC是如何进行类型转换的?如何配置一些复杂的数据类型?如果有自定义的类型如何去进行类型转换?本文将进行一一解答这些问题。

              

主要内容

1.基本类型配置

2Array类型配置

3List类型配置

4Dictionary类型配置

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 //  出处: http://terrylee.cnblogs.com
None.gif
public   class  MyComponent
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
private int[] orders;
InBlock.gif
InBlock.gif    
public int[]Orders
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
getdot.gifreturn this.orders;}
ExpandedSubBlockEnd.gif    }

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

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

ExpandedBlockEnd.gif}

这时候我们的配置文件可以如下去写

None.gif <!-- 出处:http://terrylee.cnblogs.com -->
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 // 出处: http://terrylee.cnblogs.com
None.gif
public   class  MyComponent
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
private IList _hosts;
InBlock.gif
InBlock.gif    
public MyComponent(IList hosts)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
this._hosts = hosts;
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
public IList Hosts
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gifreturn _hosts; }
ExpandedSubBlockEnd.gif    }

InBlock.gif    
//dot.gifdot.gif
ExpandedBlockEnd.gif
}

这时候我们的配置文件应该如下

None.gif <!-- 出处:http://terrylee.cnblogs.com -->
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 // 出处: http://terrylee.cnblogs.com
None.gif
public   class  MyComponent
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
private IDictionary _dictionary;
InBlock.gif
InBlock.gif    
public MyComponent(IDictionary d)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
this._dictionary = d;
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
public IDictionary Dictionary
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
getdot.gifreturn this._dictionary;}
ExpandedSubBlockEnd.gif    }

InBlock.gif    
//dot.gifdot.gif
ExpandedBlockEnd.gif
}

配置文件应该如下去写:

None.gif <!-- 出处:http://terrylee.cnblogs.com -->
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 >

或者我们可以在配置文件中分别指定KeyValue的数据类型,分别使用keyTypevalueType

None.gif <!-- 出处:http://terrylee.cnblogs.com -->
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.gifContractedBlock.gif
dot.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.gifContractedBlock.gif
dot.gif {
InBlock.gif    
private Type[] types;
InBlock.gif
InBlock.gif    
public PrimitiveConverter()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        types 
= new Type[]
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.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.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return Array.IndexOf(types, type) != -1;
ExpandedSubBlockEnd.gif    }

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

InBlock.gif        
catch(Exception ex)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.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.gifContractedSubBlock.gif    
dot.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 // 出处: http://terrylee.cnblogs.com
None.gif
public   class  MyTypeConverter : ITypeConverter
ExpandedBlockStart.gifContractedBlock.gif
dot.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系列的文章后续还有很多,希望大家继续关注!

 

参考资料

Castle的官方网站http://www.castleproject.org

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值