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

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

              

主要内容

1.基本类型配置

2Array类型配置

3List类型配置

4Dictionary类型配置

5.自定义类型转换

 

一.基本类型配置

Castle IOC的配置文件中,大家可能都已经注意一个问题了,就是不管组件接收的是什么基本数据类型,我们一律没有在配置文件中指定,也就是说,不管组件接收的类型是int型或者是String类型,我们都可以这样去配置:

<component id="MyComponent">

    
<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的参数

// 出处:http://terrylee.cnblogs.com
public class MyComponent
{
    
private int[] orders;

    
public int[]Orders
    
{

        
getreturn this.orders;}
    }

    
public MyComponent()
    
{

    }

    
public MyComponent(int[]orders)
    
{
        
this.orders = orders;
    }

}

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

<!--出处:http://terrylee.cnblogs.com-->

<?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类型的参数

//出处:http://terrylee.cnblogs.com
public class MyComponent
{
    
private IList _hosts;

    
public MyComponent(IList hosts)
    
{
        
this._hosts = hosts;
    }


    
public IList Hosts
    
{
        
get return _hosts; }
    }

    
//
}

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

<!--出处:http://terrylee.cnblogs.com-->

<?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类型的参数

//出处:http://terrylee.cnblogs.com
public class MyComponent
{
    
private IDictionary _dictionary;

    
public MyComponent(IDictionary d)
    
{
        
this._dictionary = d;
    }


    
public IDictionary Dictionary
    
{
        
getreturn this._dictionary;}
    }

    
//
}

配置文件应该如下去写:

<!--出处:http://terrylee.cnblogs.com-->

<?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>

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

<!--出处:http://terrylee.cnblogs.com-->

<?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() ); 

}

这些类型转换器之间的结构图如下:

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);

    }


}

可以看到,Castle IOC会把所有的配置参数都当作String类型接收,如果目标类型是String,则直接返回结果,否则再进行类型转换。由此我们可以分析得出,要实现自己的类型转换,有以下两步:

1.编写的自己的类型转换类,实现接口ITypeConverter

//出处:http://terrylee.cnblogs.com
public class MyTypeConverter : ITypeConverter
{
    
//
}

2.添加自己的类型转换到ConversionManager

IKernel kernel = new DefaultKernel();

IConversionManager conversionMng 
= (IConversionManager) 

    kernel.GetSubSystem( SubSystemConstants.ConversionManagerKey );

conversionMng.Add(
new MyTypeConverter());

 

关于Castle IOC容器中构建配置信息就到这里了,我总共分为了一,二两部分来讲解。Castle IOC系列的文章后续还有很多,希望大家继续关注!

 

参考资料

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

作者:TerryLee
出处:http://terrylee.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
posted @ 2006-04-24 09:58 TerryLee 阅读(6733) 评论(15)  编辑 收藏 网摘 所属分类: [12]  开源世界[09]  依赖注入

  回复  引用    
#1楼2006-04-24 10:37 | 西门子吾[未注册用户]
讲解的很详细,不错。
不知对泛型支持的怎么样?

  回复  引用  查看    
#2楼[楼主]2006-04-24 10:45 | Terrylee      
@西门子吾
谢谢支持!

我现在的研究都是在.NET1.1的平台下,2.0没有去研究。不过看Castle官方网站的介绍,应该是支持泛型的,因为在Castle ActiveRecord中是可以的。

  回复  引用    
#3楼2006-04-24 12:55 | 蒋远发[未注册用户]
写得好!
  回复  引用  查看    
#4楼[楼主]2006-04-24 13:08 | Terrylee      
@蒋远发

多谢支持:-)

  回复  引用  查看    
#5楼2006-04-24 14:26 | neuhawk      
Castle ,偶关注好久了,也不知道什么时候才用上.
  回复  引用  查看    
#6楼[楼主]2006-04-24 16:56 | Terrylee      
@neuhawk
Castle的确很不错,值得一用!

  回复  引用  查看    
#7楼2006-04-24 23:24 | Zhongkeruanjian      
TerryLee:

你的Castle.Windsor源代码在哪里下的?

我在官方网站上下的源代码是1.0.0.2的,结果发现没有
XslProcessor.xslt这个文件。但是这个文件被XslProcessor所引用。。
调试无法通过。。。。

这个类的功能是处理传进来的配置文件。。通过XslProcessor.xslt来转换。。

后来到官方网站的SVN上查,发现这个文件已经被删除掉了,估计下个版本会更改转换配置文件的方式。。

但是现在这个源代码不能用。郁闷啊。。

  回复  引用  查看    
#8楼[楼主]2006-04-25 08:10 | Terrylee      
@Zhongkeruanjian
我也是在官方网站上载的啊

我安装的是Castle.msi这个文件:-)

  回复  引用  查看    
#9楼2006-04-25 09:20 | Zhongkeruanjian      
我也是这个。安装后就是缺XslProcessor.xslt
是不是安装后还有什么动作?

要不你把XslProcessor.xslt里的代码发一份给我好了。谢谢。

地址是:lsun AT dbm-hub.com

  回复  引用  查看    
#10楼2006-04-25 11:51 | Zhongkeruanjian      
搞定了,我装了个SVN客户端,直接取Castle最新的了!:)
  回复  引用  查看    
#11楼[楼主]2006-04-25 12:00 | Terrylee      
@Zhongkeruanjian
不好意思,上午太忙了,没来得及看:)

  回复  引用    
#12楼2006-08-18 15:44 | Suren[未注册用户]
问一下哪里有Castle的配置文件的Schema(XSD)?

  回复  引用    
#13楼2006-09-29 17:26 | codelover[未注册用户]
.net开源框架qq群30017484,Castle ActiveRecord、Nhibernate、ibatisnet、IOC容器Spring.Net和Castle、等框架交流学习
  回复  引用    
#14楼2006-12-14 17:03 | 古巴[未注册用户]
初学,问两个问题:
1、请问多维数组如何配置?
2、数组里面的元素就是配置的其他component时,该如何配置,或者说支不支持这种用法?

  回复  引用    
#15楼2007-05-23 15:48 | 草房子[未注册用户]
问一个问题,我在castle官方网站上下载了MicroKernel/Windsor的实例代码GettingStartedPart1。编译时发生错误。好像是HttpServiceWatcher类在初始化时,参数IFailureNotifier[]的依赖注入未成功。IFailureNotifier是自定义的接口。我试了一下,将HttpServiceWatcher中的数组参数由IFailureNotifier[]换为int[]时无错误。




发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 383196




相关文章:

相关链接: