当前访客身份:游客 [ 登录 | 加入开源中国 ]

代码分享

当前位置:
代码分享 » C#  » 常用工具方法
分享到: 
收藏 +0
3
对依赖注入( http://www.oschina.net/code/snippet_871522_15682) 的进一步加强.
作为基本功能的注册,使用语法是:registration.register<Interface,Implementation>().
可以到了实际的项目中,要注册的接口和类可能不止一个两个,会成百上千。无论是用C#代码来注册,还是用XML文件来配置,都是开发者的噩梦。

这里,让我们来个思维的反转: 变集中配置为分散声明。
1 为要注册的类,加入RegisterInContainer的声明
2 在系统启动的时候,扫描所有的类,对有RegisterInContainer的类,找到它所有实现的接口,把这些接口和该类绑定注册。
标签: eLiteWeb

代码片段(7) [全屏查看所有代码]

1. [代码]用于装饰要注入类的Attribute.      跳至 [1] [2] [3] [4] [5] [6] [7] [全屏预览]

using System;
using System.Linq;
using Skight.eLiteWeb.Domain.BasicExtensions;

namespace Skight.eLiteWeb.Domain.Containers
{
    [AttributeUsage(AttributeTargets.Class)]
    public class RegisterInContainerAttribute : Attribute
    {
        public RegisterInContainerAttribute(LifeCycle life_cycle) {
            this.life_cycle = life_cycle;
        }

        public LifeCycle life_cycle { get; set; }
        public Type type_to_register_in_container { get; set; }

        public void register_using(Registration registration) {
            DiscreteItemResolver resolver = new TypeResolver(type_to_register_in_container);
            if (life_cycle == LifeCycle.singleton) resolver = new SingletonResolver(resolver);
            registration.register(resolver,type_to_register_in_container.all_interface().ToArray());
        }
    }
}

2. [代码]注入声明Attribute参数,指定是否单件方式生成注册类。     跳至 [1] [2] [3] [4] [5] [6] [7] [全屏预览]

namespace Skight.eLiteWeb.Domain.Containers
{
    public enum LifeCycle
    {
        single_call,
        singleton
    }
}

3. [代码]注册声明Attribute的使用示例     跳至 [1] [2] [3] [4] [5] [6] [7] [全屏预览]

//调用Container.get_an<FrontController>()将会得到FrontControllerImpl的对象

using Skight.eLiteWeb.Domain.Containers;

namespace Skight.eLiteWeb.Presentation.Web.FrontControllers
{
    [RegisterInContainer(LifeCycle.single_call)]
    public class FrontControllerImpl : FrontControllers.FrontController
    {
        private CommandResolver command_resolver;

        public FrontControllerImpl(CommandResolver commandResolver)
        {
            command_resolver = commandResolver;
        }

        public void process(WebRequest request)
        {
            command_resolver.get_command_to_process(request).process(request);
        }
    }
}

4. [代码]Registration添加一个方法:反过来,为一个解析器(实现类)注册多个接口。     跳至 [1] [2] [3] [4] [5] [6] [7] [全屏预览]

void register(DiscreteItemResolver resolver, params Type[] contracts);

5. [代码]扫描注册机,在系统启动时调用一次。     跳至 [1] [2] [3] [4] [5] [6] [7] [全屏预览]

using System.Collections.Generic;
using System.Reflection;
using Skight.eLiteWeb.Domain.BasicExtensions;
using Skight.eLiteWeb.Domain.Containers;

namespace Skight.eLiteWeb.Application.Startup
{
    public class RegistrationScanner:StartupCommand
    {
        private readonly Registration registration;
        private readonly IEnumerable<Assembly> assemblies;

        public RegistrationScanner(Registration registration, params Assembly[] assemblies)
        {
            this.registration = registration;
            this.assemblies = assemblies;
        }

        public void run()
        {
            assemblies
                .each(assembly =>
                      assembly.GetTypes()
                              .each(type =>
                                    type.run_againste_attribute<RegisterInContainerAttribute>(
                                        attribute =>
                                            {
                                                attribute.type_to_register_in_container = type;
                                                attribute.register_using(registration);
                                            })));
        }
    }
}

6. [代码]系统启动:创建注册类,然后传入必要的Assembly,调用注册机注册所有加了Attribute的类。     跳至 [1] [2] [3] [4] [5] [6] [7] [全屏预览]

using System;
using System.Collections.Generic;
using System.Reflection;
using Skight.eLiteWeb.Domain.Containers;
using Skight.eLiteWeb.Presentation.Web.FrontControllers;

namespace Skight.eLiteWeb.Application.Startup
{
    public class ApplicationStartup
    {
        public void run()
        {
            var registration = create_registration();
            new RegistrationScanner(registration,
                                               Assembly.GetAssembly(typeof (Container)),
                                               Assembly.GetAssembly(typeof (FrontController)),
                                               Assembly.GetAssembly(typeof (StartupCommand)))
                                               .run();

        }

        private Registration create_registration()
        {
            IDictionary<Type, DiscreteItemResolver> item_resolvers = new Dictionary<Type, DiscreteItemResolver>();
            Container.initialize_with(new ResolverImpl(item_resolvers));
            return new RegistrationImpl(item_resolvers);
        }
    }
}

7. [代码]Global.asax系统入口,把所有的代码串起来。     跳至 [1] [2] [3] [4] [5] [6] [7] [全屏预览]

<%@ Application Language="C#" %>
<%@ Import Namespace="Skight.eLiteWeb.Application.Startup" %>
<script  RunAt="server">

    private void Application_Start(object sender, EventArgs e)
    {
       new ApplicationStartup().run();
    }

</script>


开源中国-程序员在线工具:Git代码托管 API文档大全(120+) JS在线编辑演示 二维码 更多»

发表评论 回到顶部 网友评论(5)

  • 1楼:冷夜无霜 发表于 2013-01-05 14:41 回复此评论
    你这样方式方便了,但怎么做到热插拔呢?
  • 2楼:予沁安 发表于 2013-01-06 01:34 回复此评论

    引用来自“Simmery”的评论

    你这样方式方便了,但怎么做到热插拔呢?
    这是简易框架,主要用于三层之间的解构,没考虑插件问题。你可以自己扩展,或用第三方框架如nInject
  • 3楼:fuck_osc 发表于 2013-01-09 19:01 回复此评论
    很好,挂马的人最喜欢了。
  • 4楼:予沁安 发表于 2013-01-10 04:27 回复此评论

    引用来自“210331”的评论

    很好,挂马的人最喜欢了。
    什么是挂马?
  • 5楼:VAllen 发表于 2014-07-16 20:10 回复此评论

    引用来自“予沁安”的评论

    引用来自“210331”的评论

    很好,挂马的人最喜欢了。
    什么是挂马?
    木马。