zoukankan      html  css  js  c++  java
  • Introducing Unity Application Block


    Unity Block学习笔记

    1 What's Unity?

    1.1 轻量DI容器

    1.1.1 traditional

    1.1.1.1 constructor

    1.1.1.2 setter

    1.1.1.3 interface

    1.1.2 Unity 扩展

    1.1.2.1 property

    1.1.2.2 method call

    1.2 与其他EntLib的差异

    1.2.1 可独立安装的DI机制

    1.2.2 解决DI的途径

    1.2.2.1 通过配置

    1.2.2.2 通过代码动态注册

    1.2.3 不依赖于EntLibCoreConfiguration部分

    1.3 优势

    1.3.1 简化对象的创建过程,尤其是层次型对象

    1.3.2 借助横切方式,提供必要的抽象,对象创建的定义可以通过配置或运行时方式完成

    1.3.3 将构造过程延迟到依据容器的配置

    1.3.4 提供Service Locator功能

    1.3.4.1 container保存位置

    1.3.4.1.1 ASP.NET Session

    1.3.4.1.2 ASP.NET Application

    1.3.4.1.3 其他Client Store

    2 Unity的常用情景

    2.1 背景

    2.1.1 由于业务的复杂性,现代软件进入基于组件的软件工程时代

    2.1.2 包括业务处理组件、公共机制、还有一系列横切机制

    2.1.3 必须采用松散耦合设计

    2.1.4 但对象的创建过程往往又存在严格的依赖关系

    2.2 常用的解决模式

    2.2.1 IoC模式

    Inversion of Control (IoC) pattern. This generic pattern describes techniques for supporting a plug-in architecture where objects can "look up" instances of other objects they require.

    2.2.2 DI模式

    Dependency Injection (DI) pattern. This is a special case of the IoC pattern and is an interface programming technique based on altering class behavior without the changing the class internals. Developers code against an interface for the class and use a container that injects dependent object instances into the class based on the interface or object type. The techniques for injecting object instances are interface injection, constructor injection, property (setter) injection, and method call injection.

    2.2.3 Interception模式

    Interception pattern. This pattern introduces another level of indirection. This technique places an object between the client and the real object. A proxy is used between the client and the real object. The client behavior is the same as interacting directly to the real object, but the proxy intercepts them and solves their execution by collaborating with the real object and other objects as required.

    3 开发应用

    3.1 环境要求

    This topic describes the requirements for installing and using the Unity Application Block. It also discusses how you can extend and modify the application block using different versions of Visual Studio. The minimum requirements are the following:

     

    Microsoft Windows XP Professional, Windows Server 2003, Windows Server 2008, or Windows Vista operating system

    Microsoft .NET Framework 2.0, 3.0, or 3.5

    Microsoft Visual Studio 2005 or Visual Studio 2008 development system (any of the following editions):

    The Express Editions:

    Visual Basic 2008 Express Edition

    Visual C# 2008 Express Edition

    Visual C++ 2008 Express Edition

    Visual Web Developer 2008 Express Edition

    Standard Edition

    Professional Edition

    Team Edition for Software Developers

    Team Edition for Software Testers

    Team Edition for Software Architects

    Team Suite

    The Unity Application Block solution and project files are all in Visual Studio 2005 format, and you can open them and modify them using Visual Studio 2005. The binary assemblies provided with the application block are targeted at version 2.0 of the .NET Framework. However, you can use the Unity Application Block in applications created with Visual Studio 2008 by setting a reference to the binary assemblies.

     

    You can modify or extend the Unity Application Block using Visual Studio 2008. When you open a solution, Visual Studio 2008 will upgrade the projects to its format, and you can edit and compile the code to create assemblies targeted at version 3.5 of the .NET Framework. However, you will not be able to convert the projects back into Visual Studio 2005 format. Therefore, it is a good idea to work with a copy of the original solutions and projects.

     

    3.2 构造类型实例

    3.2.1 构造一个最简单的对象实例

           publicinterfaceIUser{ }

     

           publicclassUserA: IUser{ }

           publicclassUserB: IUser{ }

     

           publicclassObjectWithTwoProperties

           {

               objectobj1;

               objectobj2;

     

               [Dependency]

               publicobjectObj1

               {

                   get{ returnobj1; }

                   set{ obj1 = value; }

               }

     

               [Dependency]

               publicobjectObj2

               {

                   get{ returnobj2; }

                   set{ obj2 = value; }

               }

     

              publicvoidInjectInt(intmax)

               {

                   this.max = max;

               }

     

               [InjectionMethod]

               publicvoidInjectString(stringmessage, intcount)

               {

                   this.message = message;

                   this.count = count;

               }

           }

     

           [TestMethod]

           publicvoidTestCreateInstanceByInterface()

           {

               IUnityContainercontainer = newUnityContainer();

               container.RegisterType<IUser, UserA>();

               IUseruserA = container.Resolve<IUser>();

               Assert.IsInstanceOfType(userA,typeof(UserA));

           }

     

           [TestMethod]

           publicvoidTestSetterInjection()

           {

               IUnityContainercontaienr = newUnityContainer();

               ObjectWithTwoPropertiestarget = newObjectWithTwoProperties();

               Assert.IsNull(target.Obj1);

               Assert.IsNull(target.Obj2);

     

               contaienr.BuildUp(target);

               Assert.IsNotNull(target.Obj1);

               Assert.IsNotNull(target.Obj2);

           }

    3.2.2 为映射关系命名

    publicinterfaceIUser

    {

    }

     

    publicclassDefaultUser: IUser

    {

    }

     

    publicclassUserA: IUser

    {

    }

     

    publicclassUserB: IUser

    {

    }

     

    [TestMethod]

    publicvoidTestCreateDefaultTypeInstance()

    {

        IUnityContainercontainer = newUnityContainer()

            .RegisterType<IUser, DefaultUser>()

            .RegisterType<IUser, UserA>("A")

            .RegisterType<IUser, UserB>("B");

        IUseruser = container.Resolve<IUser>();

        Assert.IsInstanceOfType(user,typeof(DefaultUser));

    }

     

     

    [TestMethod]

    publicvoidTestCreateNamedTypeInstance()

    {

        IUnityContainercontainer = newUnityContainer()

            .RegisterType<IUser, DefaultUser>()

            .RegisterType<IUser, UserA>("A")

            .RegisterType<IUser, UserB>("B");

        IUseruserA = container.Resolve<IUser>("A");

        Assert.IsInstanceOfType(userA,typeof(UserA));

        IUseruserB = container.Resolve<IUser>("B");

        Assert.IsInstanceOfType(userB,typeof(UserB));

    }

    3.2.3 构造一系列简单的对象实例

    publicinterfaceIUser

    {

    }

     

    publicclassDefaultUser: IUser

    {

    }

     

    publicclassUserA: IUser

    {

    }

     

    publicclassUserB: IUser

    {

    }

     

    [TestMethod]

    publicvoidTestCreateSeriesInstances()

    {

        IUnityContainercontainer = newUnityContainer()

           .RegisterType<IUser, UserA>("A")

           .RegisterType<IUser, UserB>("B");

        IList<IUser> users = newList<IUser>(container.ResolveAll<IUser>());

        Assert.IsInstanceOfType(users[0],typeof(UserA));

        Assert.IsInstanceOfType(users[1],typeof(UserB));

    }

    3.2.4 Singleton实例

    publicinterfaceIUser

    {

    }

     

    publicclassDefaultUser: IUser

    {

    }

     

    publicclassUserA: IUser

    {

    }

     

    publicclassUserB: IUser

    {

    }

     

    [TestMethod]

    publicvoidTestCreateSingletonInstance()

    {

        IUnityContainercontainer = newUnityContainer()

            .RegisterType<IUser, DefaultUser>(newContainerControlledLifetimeManager());

        IUseruserA = container.Resolve<IUser>();

        IUseruserB = container.Resolve<IUser>();

        IUseruserC = container.Resolve<IUser>();

        Assert.IsNotNull(userA);

        Assert.IsNotNull(userB);

        Assert.IsNotNull(userC);

        Assert.AreSame(userA, userB);

        Assert.AreSame(userB, userC);

     

        container.Dispose();

    }

    3.2.5 MethodInjection

    publicclassObjectWithTwoProperties

    {

        intmax;

        stringmessage;

        intcount;

     

        publicintMax

        {

           get{ returnmax; }

        }

     

        publicstringMessage

        {

           get{ returnmessage; }

        }

     

        publicintCount

        {

           get{ returncount; }

        }

     

        [InjectionMethod]

        publicvoidInjectInt(intmax)

        {

           this.max = max;

        }

     

        [InjectionMethod]

        publicvoidInjectString(stringmessage, intcount)

        {

           this.message = message;

           this.count = count;

        }

    }

     

    [TestMethod]

    publicvoidTestMethodInjection()

    {

        IUnityContainercontainer = newUnityContainer();

        container.RegisterType<ObjectWithTwoProperties>(

           newInjectionMethod("InjectInt", 30),

           newInjectionMethod("InjectString", "Hello", 15));

        ObjectWithTwoPropertiestarget = container.Resolve<ObjectWithTwoProperties>();

        Assert.IsNotNull(target);

        Assert.AreEqual<int>(30, target.Max);

        Assert.AreEqual<string>("Hello", target.Message);

        Assert.AreEqual<int>(15, target.Count);

    }

    3.2.6 ConstructorInjection

    publicclassDepObj1

    {

        publicstringValue;

    }

     

    publicclassDepObj2

    {

        publicstringValue;

    }

     

    publicclassUserObj

    {

        stringv1;

        stringv2;

     

        [InjectionConstructor]

        publicUserObj(DepObj1obj1, DepObj2obj2)

        {

            v1 = obj1.Value;

            v2 = obj2.Value;

        }

     

        publicstringV1

        {

           get{ returnv1; }

        }

     

        publicstringV2

        {

           get{ returnv2; }

        }

    }

     

    conststringV1 = "Hello";

    conststringV2 = "World";

     

    [TestMethod]

    publicvoidTestConstructorInjection()

    {

        IUnityContainercontainer = newUnityContainer();

        UserObjtarget1 = container.Resolve<UserObj>();

        Assert.IsNotNull(target1);

       Assert.IsTrue(string.IsNullOrEmpty(target1.V1));

        Assert.IsTrue(string.IsNullOrEmpty(target1.V2));

     

        DepObj1obj1 = newDepObj1();

        obj1.Value = V1;

        DepObj2obj2 = newDepObj2();

        obj2.Value = V2;

        container.RegisterInstance<DepObj1>(obj1);

        container.RegisterInstance<DepObj2>(obj2);

        UserObjtarget2 = container.Resolve<UserObj>();

        Assert.IsNotNull(target2);

        Assert.AreEqual<string>(V1, target2.V1);

        Assert.AreEqual<string>(V2, target2.V2);

    }

    3.2.7 根据现有实例构造

    publicinterfaceIUser

    {

    }

     

    publicclassUserA: IUser{ }

    publicclassUserB: IUser{ }

     

    [TestMethod]

    publicvoidTestCreateByInstance()

    {

        UserAuserA = newUserA();

        UserBuserB = newUserB();

        IUnityContainercontainer = newUnityContainer()

            .RegisterInstance<IUser>(userA)

            .RegisterInstance<IUser>("special", userB);

     

        IUseru1 = container.Resolve<IUser>();

        IUseru2 = container.Resolve<IUser>("special");

        Assert.IsInstanceOfType(u1,typeof(UserA));

        Assert.IsInstanceOfType(u2,typeof(UserB));

    }

    3.3 Unity构造并应用

    publicinterfaceIUser

    {

        stringName { get;}

        intAge { get;}

    }

     

    publicclassUserA: IUser

    {

        #regionIUser Members

        publicstringName { get{ return"Joe"; } }

        publicintAge { get{ return20; } }

        #endregion

    }

     

    classUserStore

    {

        IUseruser;

     

        publicUserStore(IUseruser)

        {

           this.user = user;

        }

     

        publicstringUserInformatiion

        {

           get

            {

               if(this.user == null)

                   thrownewArgumentNullException("user");

               returnstring.Format("{0} is {1} years old", user.Name, user.Age);

            }

        }

    }

     

    ///<summary>

    ///Constructor Injection

    ///</summary>

    [TestMethod]

    publicvoidTestConstructorInjection()

    {

        IUnityContainercontainer = newUnityContainer();

        container.RegisterType<IUser, UserA>();

        IUseruser = container.Resolve<IUser>();

        UserStorestore = newUserStore(user);

        Assert.AreEqual<string>(

           string.Format("{0} is {1} years old","Joe", 20),

            store.UserInformatiion);

    }

    4 Unity的设计

    4.1 概要类图

    4.2 初始化过程

    When code initializes a UnityContainer instance, the constructor creates within its context instances of the classes required to prepare ObjectBuilder and pass information to it so that it can perform the appropriate object generation process. These classes are defined by ObjectBuilder and include the following:

    ·        The NamedTypesRegistry class, which stores a list of registered types

    ·        A generic List that holds references to UnityContainerExtension instances added to the container

    ·        The Locator class, which locates existing instances of registered types

    ·        The LifetimeContainer class, which manages the lifetime of registered objects and disposes of them when the container is disposed

    ·        Two instances of the StagedStrategyChain, which store the build strategies and build plans for ObjectBuilder to use when creating instances of registered types

    ·        The PolicyList class, which contains the policies ObjectBuilder will use when examining objects and classes during the build process

    During the next stage of initialization, the UnityContainer adds two container extensions named UnityDefaultStrategiesExtension and UnityDefaultBehaviorExtension that implement and manage the Unity processes.

    The UnityDefaultStrategiesExtension adds to the container context the two StagedStrategyChain instances created during initialization that specify the main strategy chain and the build plan strategy chain. These strategy chains determine how ObjectBuilder will handle constructor injection, property injection, and method call injection. The UnityDefaultStrategiesExtension also adds three ObjectBuilder policies to the current container context that specify the three attributes (the InjectionConstructor, Dependency, and InjectionMethod attributes) that ObjectBuilder will look for when reflecting over the object it creates.

    The UnityDefaultBehaviorExtension registers event handlers for the type registration events that Unity supports:

    ·        Registering. This registers the type name in the container context and adds a BuildKeyMappingPolicy to the context that specifies how ObjectBuilder will resolve type mappings. It also adds any specified lifetime manager to the context lifetime policies.

    ·        RegisteringInstance. This registers the instance in the container context and adds any specified lifetime manager to the context lifetime policies.

     

    4.3 提供的操作

    The public methods of the UnityContainer that developers use fall into two main categories:

    ·        Methods that register mappings or types. These methods raise the Registering or the RegisteringInstance event. This causes the UnityDefaultBehaviorExtension to create the appropriate policies and locator entries within the current container context.

    ·        Methods that retrieve objects. These include overrides of the Resolve, ResolveAll, and BuildUp methods. All these methods eventually call a private method of the UnityContainer class named DoBuildUp. This method retrieves the required instances of the objects that ObjectBuilder requires to perform the object creation process. These objects include the NamedTypesRegistry, Locator, LifetimeContainer, the list of container extensions, and the strategies and policies created during initialization and through registration of type mappings, singletons, and object instances. The DoBuildUp method then executes the BuildUp method in ObjectBuilder and returns the resulting object.

  • 相关阅读:
    hdu 2842 Chinese Rings
    Codeforces Round #118 (Div. 1) A 矩阵快速幂
    hdu2604 Queuing
    支付宝 生活号 获取 userId 和 生活号支付
    maven 项目使用本地jar
    nexus 私有 maven 仓库的搭建
    linux jdk 安装
    gitlab 可以上传代码,但是 不能 上传 tag 问题
    maven 内置变量
    mysql 不允许分组的问题 this is incompatible with sql_mode=only_full_group_by
  • 原文地址:https://www.cnblogs.com/utopia/p/1556931.html
Copyright © 2011-2022 走看看