• 利用标签(Attribute)和Microsoft.Practices.ObjectBuilder构造对象实例


    1.定义attribute
     1using System;
     2using System.Collections.Generic;
     3using System.Text;
     4
     5namespace JasonNet.Platform.Common
     6{
     7    /// <summary>
     8    /// <see cref="DefaultImplementationAttribute"/>标签用于定义一个接口的默认实现类型。
     9    /// </summary>
    10    /// Title: DefaultImplementationAttribute
    11    /// Author: 姜辉
    12    /// Version: 1.0
    13    /// History:
    14    ///     2006-07-13       姜辉    [创建]

    15
    16    [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class, AllowMultiple=false, Inherited=false)]
    17    public sealed class DefaultImplementationAttribute : Attribute
    18    {
    19        private Type defaultImplementationType;
    20        private string defaultImplementationTypeFullName;
    21
    22        /// <summary>
    23        /// <see cref="DefaultImplementationAttribute"/>的构造函数。
    24        /// </summary>
    25        /// <param name="defaultImplementationType">指定接口的默认实现类型</param>

    26        public DefaultImplementationAttribute(Type defaultImplementationType)
    27        {
    28            this.defaultImplementationType = defaultImplementationType;
    29        }

    30
    31        /// <summary>
    32        /// <see cref="DefaultImplementationAttribute"/>的构造函数。
    33        /// </summary>
    34        /// <param name="defaultImplementationTypeFullName">指定接口的默认实现类型的字符串表达形式</param>

    35        public DefaultImplementationAttribute(string defaultImplementationTypeFullName)
    36        {
    37            this.defaultImplementationTypeFullName = defaultImplementationTypeFullName;
    38        }

    39
    40        /// <summary>
    41        /// 指定接口的默认实现类型。
    42        /// </summary>

    43        public Type DefaultImplementationType
    44        {
    45            get
    46            {
    47                return defaultImplementationType;
    48            }

    49        }

    50
    51        /// <summary>
    52        /// 指定接口的默认实现类型的字符串表达形式。
    53        /// </summary>

    54        public string DefaultImplementationTypeFullName
    55        {
    56            get
    57            {
    58                return defaultImplementationTypeFullName;
    59            }

    60        }

    61    }

    62}

    2.定义构造容器
      1using System;
      2using System.IO;
      3using System.Globalization;
      4using System.Collections.Generic;
      5using System.Text;
      6using System.Reflection;
      7using Microsoft.Practices.ObjectBuilder;
      8
      9using JasonNet.Platform.Common.Properties;
     10
     11namespace JasonNet.Platform.Common
     12{
     13    /// <summary>
     14    /// <see cref="ObjectContainer"/>用于创建、获取容器中的对象实例。
     15    /// Title: ObjectContainer
     16    /// Author: 姜辉
     17    /// Version: 1.0
     18    /// History:
     19    ///     2006-07-13 姜辉 [创建]

     20 
     21    public static class ObjectContainer
     22    {
     23        private static IBuilder<BuilderStage> builder = new Builder();
     24        private static Locator locator =  new Locator();
     25
     26        private const string InterfacePrefix = "I";
     27        private const string AbstractClassPrefix = "Base";
     28        private const string DefaultImplNamespaceSuffix = "DefaultImpl.";
     29
     30        /// <summary>
     31        /// 根据指定的对象类型构造对象实例。
     32        /// </summary>
     33        /// <remarks>
     34        /// <para>
     35        /// <see cref="ObjectContainer"/>不支持简单值类型的构造,因此,如果<typeparamref name="T"/>是简单值类型,
     36        /// 将抛出<see cref="ArgumentException"/>
     37        /// </para>
     38        /// <para>
     39        /// 如果<typeparamref name="T"/>是非静态的实现类,则直接构建<typeparamref name="T"/>的对象实例。
     40        /// </para>
     41        /// <para>
     42        /// 如果<typeparamref name="T"/>是接口或抽象类,则<see cref="ObjectContainer"/>将按以下规则来创建该接口
     43        /// 或抽象类的实现类对象实例:
     44        /// <list type="bullet">
     45        /// <item>
     46        /// <description>
     47        /// 首先检测<typeparamref name="T"/>是否标记了<see cref="DefaultImplementationAttribute"/>标签来指定默认
     48        /// 的实现类,如果指定了合法的默认实现类,则会构造出指定的默认实现类的对象实例;如果通过标签指定的默认实
     49        /// 现类不合法,则会抛出<see cref="TypeNotMatchException"/><see cref="DefaultImplementationNotFoundException"/>异常。
     50        /// </description>
     51        /// </item>
     52        /// <item>
     53        /// <description>
     54        /// 如果<typeparamref name="T"/>没有使用<see cref="DefaultImplementationAttribute"/>标签来指定默认的实现
     55        /// 类,则会根据<c>JasonNet</c>平台默认的匹配关系(默认实现类的命名空间为接口命名空间 + ".DefaultImpl",
     56        /// 类名为接口名称去掉前缀“I”,或基类名称去掉“Base”)来查找默认实现类,如果能够找到,则构造出该默认
     57        /// 实现类的对象实例,如果无法找到,则抛出<see cref="DefaultImplementationNotFoundException"/>异常。
     58        /// </description>
     59        /// </item>
     60        /// </list>
     61        /// </para>
     62        /// <para>
     63        /// 从以上对于接口或抽象类的默认实现对象的构造规则中可以看出,要成功构造一个接口或抽象类的默认实现类对象
     64        /// ,需要满足以下任意一项:
     65        /// <list type="number">
     66        /// <item>
     67        /// <description><typeparamref name="T"/>使用<see cref="DefaultImplementationAttribute"/>进行了正确的
     68        /// 配置,即<see cref="DefaultImplementationAttribute"/>指定的默认实现类确实实现了<typeparamref name="T"/>
     69        /// 接口或抽象类。</description>
     70        /// </item>
     71        /// <item>
     72        /// <description>
     73        /// 如果<typeparamref name="T"/>没有使用<see cref="DefaultImplementationAttribute"/>标签来指定默认的实现
     74        /// 类,则要求<typeparamref name="T"/>接口或抽象类、以及默认实现类的命名都遵循以下规范:1,接口必须以<c>
     75        /// I</c>作前缀,抽象类必须以<c>Base</c>作前缀;2,默认实现类的命名空间为接口命名空间 + ".DefaultImpl";
     76        /// 3,默认实现类的名称为接口名称去掉前缀“I”,或抽象类的名称去掉前缀“Base”,如下例所示:
     77        /// </description>
     78        /// </item>
     79        /// </list>
     80        /// <example>
     81        /// 以下是使用<see cref="DefaultImplementationAttribute"/>来配置接口与其默认实现类的示例,该情况下使用本
     82        /// 方法传入IUserManager接口可以构造出UserManager的实例。
     83        /// <code>
     84        /// namespace JasonNet.Platform.Security
     85        /// {
     86        ///     [DefaultImplementation(typeof(JasonNet.Platform.Security.UserManager))]
     87        ///     public interface IUserManager {}
     88        /// }
     89        /// 
     90        /// namespace JasonNet.Platform.Security
     91        /// {
     92        ///     public class UserManager : IUserManager {}
     93        /// }
     94        /// </code>
     95        /// 以下是使用<see cref="DefaultImplementationAttribute"/>来配置抽象类与其默认实现类的示例,该情况下使用
     96        /// 本方法传入BizLogDatabaseAdapter抽象类可以构造出基于SQL Server实现的SqlBizLogDatabaseAdapter的实例。
     97        /// <code>
     98        /// namespace JasonNet.Platform.Logging.Database
     99        /// {
    100        ///     [DefaultImplementation(typeof(JaonNet.Platform.Logging.Database.SqlBizLogDatabaseAdapter))]
    101        ///     public abstract class BizLogDatabaseAdapter {}
    102        /// }
    103        /// 
    104        /// namespace JasonNet.Platform.Logging.Database
    105        /// {
    106        ///     public class SqlBizLogDatabaseAdapter : BizLogDatabaseAdapter {}
    107        /// }
    108        /// </code>
    109        /// 以下是按<c>JasonNet平台默认的匹配关系</c>定义的接口与其默认实现类的示例,该情况下使用本方法传入
    110        /// IUserManager接口可以构造出UserManager的实例。
    111        /// <code>
    112        /// namespace JasonNet.Platform.Security
    113        /// {
    114        ///     public interface IUserManager {}
    115        /// }
    116        /// 
    117        /// namespace JasonNet.Platform.Security.DefaultImpl
    118        /// {
    119        ///     public class UserManager : IUserManager {}
    120        /// }
    121        /// </code>
    122        /// 以下是按<c>JasonNet平台默认的匹配关系</c>定义的抽象类与其默认实现类的示例,该情况下使用本方法传入
    123        /// BaseBizLogDatabaseAdapter抽象类可以构造出BizLogDatabaseAdapter的实例。
    124        /// <code>
    125        /// namespace JasonNet.Platform.Logging.Database
    126        /// {
    127        ///     public abstract class BaseBizLogDatabaseAdapter {}
    128        /// }
    129        /// 
    130        /// namespace JasonNet.Platform.Logging.Database.DefaultImpl
    131        /// {
    132        ///     public class BizLogDatabaseAdapter : BaseBizLogDatabaseAdapter {}
    133        /// }
    134        /// </code>
    135        /// 以下是按<c>JasonNet</c>平台为解决工程间循环引用实现类的示例,该情况下使用本方法传入
    136        /// 指定接口的默认实现类型的字符串表达形式来构造出其实例。
    137        /// <code>
    138        /// namespace *****.****.DE.InnerInterfaces 
    139        /// {
    140        /// [DefaultImplementation("*****.****.DE.DE.BusinessLogic.DesignProxyServiceFacade,*****.****.DE.BusinessLogic")]
    141        /// public interface IDeDeInnerInterface
    142        ///  {
    143        ///  IList<String> GetDesignCompanyByProjectNo(string projectNo);
    144        ///  }
    145        /// }
    146        /// namespace *****.****.**.DE.InnerInterfaces  
    147        /// {
    148        /// public interface IDesignProxyServiceFacade : IDeDeInnerInterface
    149        /// {
    150        ///  此处回到配置接口与其默认实现类的示例
    151        /// }
    152        /// </code>
    153        /// </example>
    154        /// </para>
    155        /// <para>
    156        /// 对于以上各种情况的实现类对象实例的创建,默认情况下,都将使用实现类的第一个构造函数来构造对象实例,
    157        /// 如果第一个构造函数中含有参数,则对于简单值类型以该类型的默认值为参数值;对于对象类型,会在容器中去
    158        /// 查找是否已经有该类型的对象存在,如果存在,则用该对象作为参数值,如果不存在则构造一个新的该类型的对
    159        /// 象作为参数值(在构造该类型的对象时如果又需要参数,则类似地按上述步骤进行,即一层层地递归往下找,直
    160        /// 到所有的依赖对象都被构造后,该对象才会被构造)。由于带参数的构造方式非常复杂,强烈建议使用不带参数
    161        /// 的构造函数来构造对象,即始终把不带参数的构造函数放在代码的最前面。
    162        /// </para>
    163        /// </remarks>
    164        /// <typeparam name="T">要构造的对象的类型</typeparam>
    165        /// <returns>构造的对象实例</returns>
    166        /// <exception cref="ArgumentException">
    167        /// 当<typeparamref name="T"/>是简单值类型、或在T(或T的默认实现类)中无法找到构造所需的构造函数时抛出
    168        /// 的异常。</exception>
    169        /// <exception cref="TypeNotMatchException">
    170        /// 当<typeparamref name="T"/>上的<see cref="DefaultImplementationAttribute"/>标签所指定的默认实现类类
    171        /// 型与<typeparamref name="T"/>不匹配(并没有实现T或从T派生)时抛出的异常。</exception>
    172        /// <exception cref="DefaultImplementationNotFoundException">
    173        /// 当通过平台默认的匹配关系无法找到<typeparamref name="T"/>的默认实现类时所抛出的异常。
    174        /// </exception>

    175        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design""CA1004:GenericMethodsShouldProvideTypeParameter")]
    176        public static T BuildUp<T>()
    177        {
    178            return (T)BuildUp(typeof(T));
    179        }

    180
    181        internal static object BuildUp(Type typeToBuild)
    182        {
    183            Type reflectionType = null;
    184
    185            // typeToBuild 如果是值类型或者静态类时
    186            if (typeToBuild.IsValueType || (typeToBuild.IsAbstract && typeToBuild.IsSealed))
    187            {
    188                throw new ArgumentException(
    189                    String.Format(CultureInfo.CurrentUICulture,
    190                    Resources.ExceptionTypeIsValueTypeOrStaticClass, typeToBuild.Name));
    191            }

    192
    193            // typeToBuild是接口或抽象类
    194            if (typeToBuild.IsAbstract)
    195            {
    196                object[] defaultImplAttrs = typeToBuild.GetCustomAttributes(typeof(DefaultImplementationAttribute), false);
    197                if (defaultImplAttrs.Length == 0)
    198                {
    199                    // 没有标签,按照默认规则寻找
    200
    201                    // 如果类型的命名不符合规范,则抛出异常
    202                    if (!typeToBuild.Name.StartsWith(ObjectContainer.InterfacePrefix) &&
    203                        !typeToBuild.Name.StartsWith(ObjectContainer.AbstractClassPrefix))
    204                    {
    205                        throw new IllegalTypeNameException(new string[] { typeToBuild.FullName });
    206                    }

    207
    208                    StringBuilder defaultImplTypeString = new StringBuilder();
    209                    defaultImplTypeString.Append(typeToBuild.FullName.Substring(0, typeToBuild.FullName.LastIndexOf("."+ 1));
    210                    defaultImplTypeString.Append(DefaultImplNamespaceSuffix);
    211
    212                    if (typeToBuild.IsInterface)
    213                    {
    214                        // 接口名称去掉前缀“I”
    215                        defaultImplTypeString.Append(typeToBuild.Name.Substring(1));
    216                    }

    217                    else
    218                    {
    219                        //抽象类的名称去掉前缀“Base”
    220                        defaultImplTypeString.Append(typeToBuild.Name.Substring(4));
    221                    }

    222                    defaultImplTypeString.Append("");
    223                    defaultImplTypeString.Append(typeToBuild.Assembly.FullName);
    224
    225                    reflectionType = SearchForTypeToBuild(defaultImplTypeString.ToString());
    226
    227                    // 当没有找到默认实现类
    228                    // 或者找到的是仍然是接口或者抽象类时
    229                    if (reflectionType == null ||
    230                        !typeToBuild.IsAssignableFrom(reflectionType) ||
    231                        reflectionType.IsAbstract ||
    232                        reflectionType.IsInterface)
    233                    {
    234                        throw new DefaultImplementationNotFoundException(new string[] { typeToBuild.FullName });
    235                    }

    236                }

    237                else
    238                {
    239                    // 有标签
    240                    DefaultImplementationAttribute defImpl = defaultImplAttrs[0as DefaultImplementationAttribute;
    241
    242                    if (!String.IsNullOrEmpty(defImpl.DefaultImplementationTypeFullName))
    243                    {
    244                        reflectionType = SearchForTypeToBuild(defImpl.DefaultImplementationTypeFullName);
    245                    }

    246                    else
    247                    {
    248                        reflectionType = defImpl.DefaultImplementationType;
    249                    }

    250
    251                    // 标签所指定的默认实现类类型与typeToBuild不匹配(并没有实现typeToBuild或从typeToBuild派生)
    252                    // 或者默认的实现也是一个接口或抽象类
    253                    if (reflectionType == null)
    254                    {
    255                        throw new DefaultImplementationNotFoundException(new string[] { typeToBuild.FullName });
    256                    }

    257                    if (reflectionType == typeToBuild ||
    258                        !typeToBuild.IsAssignableFrom(reflectionType) ||
    259                        reflectionType.IsAbstract ||
    260                        reflectionType.IsInterface)
    261                    {
    262                        throw new TypeNotMatchException();
    263                    }

    264                }

    265
    266                return builder.BuildUp(locator, reflectionType, nullnull);
    267            }

    268            else
    269            {
    270                // T是非静态的实现类时,检查其是否具有有效的构造函数
    271                if (typeToBuild.GetConstructors().Length == 0)
    272                {
    273                    throw new ArgumentException(
    274                        String.Format(CultureInfo.CurrentUICulture, 
    275                        Resources.ExceptionTypeHasNoConstructors, typeToBuild.Name));
    276                }

    277
    278                return builder.BuildUp(locator, typeToBuild,nullnull);
    279            }

    280        }

    281
    282        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design""CA1031:DoNotCatchGeneralExceptionTypes")]
    283        private static Type SearchForTypeToBuild(string defaultImplTypeString)
    284        {
    285            Type reflectedType = null;
    286
    287            try
    288            {
    289                reflectedType = Type.GetType(defaultImplTypeString);
    290            }

    291            catch
    292            {
    293            }

    294            return reflectedType;
    295        }

    296    }

    297}

    298
  • 相关阅读:
    linux下安装redis 3.2.1
    redis 登入,检查
    断写了一年的博客~~
    前端面试的感想
    http和web缓存
    http请求报文和响应报文(2)
    http请求报头和响应报头(1)
    网络编程(一)
    防恶意解析,禁止用IP访问网站的Apache设置 修改 httpd.conf 实现
    About English Web Site Font
  • 原文地址:https://www.cnblogs.com/jiangshaofen/p/876817.html
Copyright © 2020-2023  润新知