SharePoint计时器作业中的Ninject依赖项注入

时间:2012-07-21 08:58:40

标签: sharepoint dependency-injection web-config ninject nlog

我使用Onion架构成功实现了使用Ninject依赖注入和其他基础架构(如NLog日志记录等)的企业SharePoint解决方案。使用HttpModule作为注入框架的组合根,它非常适合普通的Web请求:

public class SharePointNinjectHttpModule: IHttpModule, IDisposable
    {
        private readonly HttpApplication _httpApplication;

        public void Init(HttpApplication context)
        {
            if (context == null) throw new ArgumentException("context");

            Ioc.Container = IocContainerFactory.CreateContainer();
        }

        public void Dispose()
        {
            if(_httpApplication == null) return;
            _httpApplication.Dispose();
            Ioc.Container.Dispose();
        } 
    }

CreateContainer方法从单独的类库加载Ninject模块,并抽象出我的ioc容器。 对于普通的Web应用程序请求,我使用了一个名为Ioc的注入器的共享静态类。 UI层具有MVP模式实现。例如,在aspx页面中,演示者的构造如下:

presenter = Ioc.Container.Get<SPPresenter>(new Ninject.Parameters.ConstructorArgument("view", this));

我仍然依赖于参数的Ninject参考。有没有办法抽象这个,除了在界面中映射很多方法?我不能只为参数传递简单类型吗?

注入本身效果很好,但是在使用外部进程(如SharePoint计时器作业)时遇到了困难。从这里重用ioc容器显然是一个可怕的想法,因此它需要自己引导依赖项。此外,它需要从Web应用程序池加载配置,而不是管理Web应用程序。否则,该作业只能在应用程序服务器上运行。这样,作业可以在任何Web服务器上运行,并且您的SharePoint功能只需要将配置等部署到Web应用程序。

这是我的计时器作业的执行方法,它打开关联的Web应用程序配置并将其传递给日志记录服务(nlog)并从外部Web配置服务读取它的配置。我编写的代码读取配置文件中的自定义部分并初始化NLog日志记录基础结构。

public override void Execute(Guid contentDbId)
        {
            try
            {
                using (var ioc = IocContainerFactory.CreateContainer())
                {                    
                    // open configuration from web application
                    var configService = ioc.Get<IConfigService>(new ConstructorArgument("webApplicationName", this.WebApplication.Name));

                    // get logging service and set with web application configuration
                    var logginService = ioc.Get<ILoggingService>();
                    logginService.SetConfiguration(configService);

                    // reapply bindings
                    ioc.Rebind<IConfigService>().ToConstant(configService);
                    ioc.Rebind<ILoggingService>().ToConstant(logginService);

                    try
                    {
                        logginService.Info("Test Job started.");

                        // use services etc...
                        var productService = ioc.Get<IProductService>();
                        var products = productService.GetProducts(5);
                        logginService.Info("Got products: " + products.Count() + " Config from web application: " + configService.TestConfigSetting);

                        logginService.Info("Test Job completed.");
                    }
                    catch (Exception exception)
                    {
                        logginService.Error(exception);
                    }
                }
            }
            catch (Exception exception)
            {
                EventLog.WriteError(exception, "Exception thrown in Test Job.");
            }
        }

这不会使定时器作业足够稳健,并且有很多锅炉板代码。我的问题是如何改进这种设计?它不是最优雅的,我正在寻找一种方法来抽象计时器作业操作代码,并为每个计时器作业注入它的依赖关系。如果您认为这是一个好方法,我想听听您的意见。或者,如果有人遇到过类似的问题?感谢

1 个答案:

答案 0 :(得分:0)

我想我已经用上面的演示者构造代码回答了我自己的问题。在项目中使用依赖项注入时,注入本身并不重要,但它改变编写代码的方式更为重要。我需要使用类似的模式,例如我的SharePoint计时器作业操作的命令。我只是想更好地处理自举。