博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Castle IOC容器构建配置详解(二)
阅读量:6763 次
发布时间:2019-06-26

本文共 6207 字,大约阅读时间需要 20 分钟。

摘要:在前一篇文章中我们并没有考虑配置的组件参数是什么类型,也没有在配置文件中指定过类型,那么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
 ,如需转载请自行联系原作者
你可能感兴趣的文章
SublimeText3按ctrl+b执行python无反应
查看>>
linux之各个文件夹作用
查看>>
posix多线程有感--线程高级编程(条件变量属性)
查看>>
linux内核mem_cgroup浅析
查看>>
Java 反射实例
查看>>
linux软件安装习惯
查看>>
字符串和ASCII之间的转换
查看>>
python3学习笔记(二):Python初识
查看>>
Servlet 文件上传
查看>>
JQ - 绑定(on)/解绑(off)事件(浅显的见解)
查看>>
JavaScript setInterval(定时/延时调用函数)
查看>>
Quartz.NET 任务调度教程。
查看>>
华为oj之字符串反转
查看>>
数据访问
查看>>
JSP里面的虚拟目录
查看>>
【329】word 替换文本高级用法
查看>>
自动化测试用例编写原则
查看>>
crontab定时任务以及其中中文乱码问题
查看>>
CSAPP buffer lab记录——IA32版本
查看>>
Hyperledger fabric多机的环境部署
查看>>