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

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器镜像服务 ACR,镜像仓库100个 不限时长
简介:
摘要:在前一篇文章中我们并没有考虑配置的组件参数是什么类型,也没有在配置文件中指定过类型,那么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 >
或者我们可以在配置文件中分别指定 KeyValue的数据类型,分别使用 keyTypevalueType
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  ,如需转载请自行联系原作者

相关文章
|
5天前
|
Kubernetes Cloud Native 微服务
企业级容器部署实战:基于ACK与ALB灵活构建云原生应用架构
这篇内容概述了云原生架构的优势,特别是通过阿里云容器服务Kubernetes版(ACK)和应用负载均衡器(ALB)实现的解决方案。它强调了ACK相对于自建Kubernetes的便利性,包括优化的云服务集成、自动化管理和更强的生态系统支持。文章提供了部署云原生应用的步骤,包括一键部署和手动部署的流程,并指出手动部署更适合有技术背景的用户。作者建议在预算允许的情况下使用ACK,因为它能提供高效、便捷的管理体验。同时,文章也提出了对文档改进的建议,如添加更多技术细节和解释,以帮助用户更好地理解和实施解决方案。最后,展望了ACK未来在智能化、安全性与边缘计算等方面的潜在发展。水文一篇,太忙了,见谅!
|
11天前
|
XML Java 数据库连接
Spring6(二):IoC容器(2)
Spring6(二):IoC容器
17 2
|
11天前
|
安全 关系型数据库 开发者
Docker Compose凭借其简单易用的特性,已经成为开发者在构建和管理多容器应用时不可或缺的工具。
Docker Compose是容器编排利器,简化多容器应用管理。通过YAML文件定义服务、网络和卷,一键启动应用环境。核心概念包括服务(组件集合)、网络(灵活通信)、卷(数据持久化)。实战中,编写docker-compose.yml,如设置Nginx和Postgres服务,用`docker-compose up -d`启动。高级特性涉及依赖、环境变量、健康检查和数据持久化。最佳实践涵盖环境隔离、CI/CD、资源管理和安全措施。案例分析展示如何构建微服务应用栈,实现一键部署。Docker Compose助力开发者高效驾驭复杂容器场景。
30 1
|
11天前
|
XML Java 数据格式
Spring6(二):IoC容器(3)
Spring6(二):IoC容器(3)
14 1
|
11天前
|
XML Java 数据格式
Spring6(二):IoC容器(1)
Spring6(二):IoC容器(1)
21 1
|
11天前
|
Java Spring 容器
Spring6(二):IoC容器(4)
Spring6(二):IoC容器(4)
9 0
|
27天前
|
NoSQL 关系型数据库 Redis
Docker的通俗理解和通过宿主机端口访问Redis容器的实例
本文目标:引导初学者入门Docker,理解镜像、容器和宿主机概念,学习常用Docker命令,特别是如何创建并从Redis容器通过宿主机端口访问。 关键点: - Docker核心:镜像(类)、容器(实例)、宿主机(运行环境)。 - `docker pull` 拉取镜像,如 `redis:3.0`。 - `docker run -d --name` 后台运行容器,如 `my-redis`。 - `-p` 参数做端口映射,如 `6379:6379`。 - `docker exec -it` 交互式进入容器,如 `bash` 或执行命令。
111 4
|
24天前
|
前端开发 安全 数据库
Web架构&前后端分离站&Docker容器站&集成软件站&建站分配
Web架构&前后端分离站&Docker容器站&集成软件站&建站分配
|
7天前
|
边缘计算 物联网 开发者
什么是容器Docker?
什么是容器?容器,也叫Docker,是一个开源的容器化平台,用于开发、测试和部署应用程序。通过将软件打包为标准化的单元(容器),使得应用程序可以在任何地方一致地运行,不论是在开发者的本地机器上,还是在云计算平台上。Docker容器包含了应用程序运行所需的一切,包括代码、运行时、系统工具、系统库等,从而解决了“在我这里可以正常工作,但在服务器上不行”的问题。
30 1
|
11天前
|
存储 监控 安全
Docker Compose:轻松实现容器编排的利器
【7月更文挑战第2天】 1. **基础与概念**:服务(多容器实例)、网络(灵活通信)、卷(数据持久化)和配置(安全管理)。 2. **实战指南**:安装Compose,编写`docker-compose.yml`文件,启动应用,并介绍依赖、环境变量、健康检查和数据持久化。 3. **最佳实践**:环境隔离、CI/CD集成、资源管理、日志监控、安全策略及案例分析,展示完整应用栈搭建。
31 1