zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    vs2019+GLFW+GLAD出现无法解析的外部符号
    图的着色算法
    Head First C# 实验室2(冒险游戏)
    击中和击不中变换
    开运算和闭运算
    膨胀与腐蚀
    两数相加(C#数据结构和算法练习)
    C# 特性和索引(C#学习笔记06)
    C# 索引器(C#学习笔记05)
    C# yield checked,unchecked lock语句(C#学习笔记04)
  • 原文地址:https://www.cnblogs.com/Terrylee/p/383196.html
Copyright © 2011-2022 走看看