• Castle 多继承选择


    Castle 多继承选择

    很多时候,我们定义了一个接口,但是这个接口会有多种不同的,这时IOC构造函数注入的时候,就需要自动选择对应的实现。

    public interface ITestService {}
    
    public class TestService : IService
    {
         public string test()
         {
             return "test"
         }
    }
    
    public class TestService_New : ICalculatorService
    {
         public string test()
         {
             return "test new";
         }
    }
    

    此时,我们大多数情况下,需要用TestService来实现ITestService,但是少部分情况下,需要用TestService_New实现ITestService。

    解决方案一

    IOC中只实现需要用到的类:

    Component.For<ITestService>()
        .ImplementedBy<TestService>() 
    

    如果在某些地方部署时,修改为
    Component.For()
    .ImplementedBy<TestService_New>()

    这样每次部署的时候都需要修改代码,而且需要手写的规则会越来越多。

    解决方案二

    参考了Castle的WIKI,发现了可以ServiceOverrides重写实现:

     Component.For<ITestService>()
        .ImplementedBy<TestService>() 
        .Named("myservice.default"),
    Component.For<ITestService>()
        .ImplementedBy<TestService_New>()
        .Named("myservice.new"),
    
    Component.For<TestController>()
        .ServiceOverrides(ServiceOverride.ForKey("myService").Eq("myservice.new"))
    

    尝试了一下,VS提示改方法已过世,建议使用Dependency.OnComponent代替。
    Component.For().
    .DependsOn(Dependency.OnComponent<ITestService, TestService_New>())

    修改代码之后,怎么都不起作用。重新翻看官方WIKI,发现了IsDefault方法,当多个类实现同一个接口时,可以通过IsDefault来置为默认实现。

    解决方案三

    			 //先通过DefaultInterfaces加载正常实现 
                 Classes.FromAssembly(assembly)
                 .IncludeNonPublicTypes()
                 .BasedOn<IApplicationService>()
                 .WithService.DefaultInterfaces()
                 .LifestyleTransient()
                 .Configure(c =>
                 {
                     c.Interceptors<ExceptionInterceptor, TransactionInterceptor>();
                     c.Named(c.Implementation.Name);
                 }),
    			 //根据WEBCONFIG加载特殊实现,并设置为默认实现
                 Classes.FromAssembly(assembly)
                .IncludeNonPublicTypes()
                .BasedOn<IApplicationService>()
                .WithService.Select((type, @base) =>
                          type.GetAllInterfaces()
                              .Where(i => type.Name.Contains(GetInterfaceNameFromConf(i))))
                .LifestyleTransient()
                .Configure(c =>
                {
                    c.Interceptors<ExceptionInterceptor, TransactionInterceptor>().IsDefault()
    				.Named(c.Implementation.FullName +  "_" + ConfigurationManager.AppSettings["City"]);
                })
    
    
    			private string GetInterfaceNameFromConf(Type @interface)
    	        {
    	            var name = @interface.Name;
    	            if ((name.Length > 1 && name[0] == 'I') && char.IsUpper(name[1]))
    	            {
    	                return name.Substring(1) + "_" + ConfigurationManager.AppSettings["City"];
    	            }
    	            return name;
    	        }
    

    OK,大功告成。

  • 相关阅读:
    初探XML
    Hibernate 由实体类与配置文件的配置关系生成数据库中的表
    利用JSP中的过滤器解决中文乱码问题
    关于iBatis配置xml文件时出现中文注释出错的一个问题(很坑爹.)
    Myeclipse中xml文件里自动提示消失解决办法
    iBatis的基本配置+CRUD操作
    Myeclipse下配置svn
    Hibernate与iBastis 比较(转载)
    本人了解的分页查询
    Hibernate五大核心接口简介
  • 原文地址:https://www.cnblogs.com/lazio10000/p/5266876.html
Copyright © 2020-2023  润新知