zoukankan      html  css  js  c++  java
  • Topshelf的Ioc实现

    在前面使用Topshelf的文章里,我们的工作类TownCrier使用的是无参数的构造函数,满足测试的目的。在实际的开发过程中,我们常常需要使用带有参数的构造函数,就不可避免的使用Ioc的技术。在这里我们使用的是Topshelf.Autofac这个开源框架

    1.安装Topshelf.Autofac 

    install-package Topshelf.Autofac -Version 3.1.0

    2.创建带有参数的TownCrier构造函数类

        public class TownCrier
        {
            readonly Timer _timer;
            private AM am;
            public TownCrier(AM parameter)
            {
                am = parameter;
                _timer = new Timer(1000) { AutoReset = true };
                _timer.Elapsed += (sender, eventArgs) => Console.WriteLine("It is {0} and all is well", DateTime.Now);
            }
            public void Start() { _timer.Start(); }
            public void Stop() { _timer.Stop(); }
        }
    
        public class AM
        {
            public string Name { get; set; }
        }

    这里纯粹是为了进行测试,AM类没有任何其他方法,但可以达到测试的目的。

    3.配置Ioc

    public static void TestIoc()
            {
                // Autofac
                var builder = new ContainerBuilder();
                builder.RegisterType<TownCrier>();
                builder.RegisterType<AM>();
                var container = builder.Build();
    
                var rc = HostFactory.Run(x =>                                   //1
                {
                    x.Service<TownCrier>(s =>                                   //2
                    {
                        s.ConstructUsing(() => container.Resolve<TownCrier>());                //3
                        s.WhenStarted(tc => tc.Start());                         //4
                        s.WhenStopped(tc => tc.Stop());                          //5
                    });
                    x.RunAsLocalSystem();                                       //6
    
                    x.SetDescription("Sample Topshelf Host");                   //7
                    x.SetDisplayName("Stuff");                                  //8
                    x.SetServiceName("Stuff");                                  //9
                });                                                             //10
    
                var exitCode = (int)Convert.ChangeType(rc, rc.GetTypeCode());  //11
                Environment.ExitCode = exitCode;
            }

    代码中的红色版本是配置的主要地方,简单2点,一是将涉及到的类,通过RegisterType方法注册进来。二是ConstructUsing函数使用函数表达式container.Resolve方法注册我们的工作类TownCrier。

    在测试这段代码的时候,遇见的问题是根据官方提供的demo案例是不对的,根本没有对应的方法,可能是不同版本或者github网站代码和nuget安装代码不是同一份的缘故,反正这里是一个坑。以下是官方Demo:

    static void Main(string[] args)
    {
        // Create your container
        var builder = new ContainerBuilder();
        builder.RegisterType<SampleDependency>().As<ISampleDependency>();
        builder.RegisterType<SampleService>();
        var container = builder.Build();
    
        HostFactory.Run(c =>
        {
            // Pass it to Topshelf
            c.UseAutofacContainer(container);
    
            c.Service<SampleService>(s =>
            {
                // Let Topshelf use it
                s.ConstructUsingAutofacContainer();
                s.WhenStarted((service, control) => service.Start());
                s.WhenStopped((service, control) => service.Stop());
            });
        });
    }

    以上代码测试通过之后,就对Topshelf.Autofac的依赖注入有了基本了解,就可以着手自己实际业务的Ioc处理了。

    实际项目中的应用代码案例:

            public static void RunService()
            {
                // IOC Autofac
                var builder = new ContainerBuilder();
                builder.RegisterAssemblyTypes(Assembly.Load("HengShen.Pts.Domain")).Where(i => i.Namespace == "HengShen.Pts.Domain.Services");
                builder.RegisterAssemblyTypes(Assembly.Load("HengShen.Pts.Domain")).Where(i => i.Namespace == "HengShen.Pts.Domain.TopshelfSevice");
                builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>));
                builder.RegisterType<SqlUowDbContext>().As<ISqlUnitOfWork>();
                var container = builder.Build();
                
                var rc = HostFactory.Run(x =>                                   //1
                {
                    try
                    {
                        x.Service<WavePlanSyncService>(s =>                                   //2
                        {
                            s.ConstructUsing(() => container.Resolve<WavePlanSyncService>());
                            s.WhenStarted(tc => tc.Start());
                            s.WhenStopped(tc => tc.Stop()); 
                        });
                        x.RunAsLocalSystem();                                       //6
    
                        x.SetDescription("Sample Topshelf Host");                   //7
                        x.SetDisplayName("Stuff");                                  //8
                        x.SetServiceName("Stuff");                                  //9
                    }
                    catch(Exception ex)
                    {
                        string m = ex.Message;
                    }
                });                                                             //10
    
                var exitCode = (int)Convert.ChangeType(rc, rc.GetTypeCode());  //11
                Environment.ExitCode = exitCode;
            }

    考虑到以后还会有新的task加入,这里就不在一个个的去注册Service类,而是通过程序集的方式将所有的Service一起注册进来,而这些Service类又依赖Repository,所以也将对应的泛型形式注册进来,SqlUowDbContext是Repository要使用的,所以也注册进来。在测试的时候,使用了以下方式的代码,程序报错。原因是这里我们使用的是控制台程序,没有网络请求

    builder.RegisterType<SqlUowDbContext>().As<ISqlUnitOfWork>().InstancePerRequest();

    改正后的代码是

    builder.RegisterType<SqlUowDbContext>().As<ISqlUnitOfWork>();

    再编译运行,程序不在出错,打印出我们预先设定的内容,IOC依赖注入处理就此完毕。

  • 相关阅读:
    【STM32F407】第2章 嵌入式网络协议栈基础知识
    【STM32H7】第1章 当前主流的小型嵌入式网络协议栈
    【STM32F429】第1章 当前主流的小型嵌入式网络协议栈
    【STM32F407】第1章 当前主流的小型嵌入式网络协议栈
    Linux(centos)使用docker安装pdf2htmlEX
    JAVA实现查询栏目、类别(菜单)返回树结构(递归)
    maven打包 运行出现 错误: 找不到或无法加载主类 jar
    IDEA版本2020.1全局MAVEN配置
    注解版mybatis动态语句将空字符串转换为null
    Windows系统安装ActiveMQ
  • 原文地址:https://www.cnblogs.com/crazyguo/p/8490681.html
Copyright © 2011-2022 走看看