1

我已经使用 Ninject 依赖注入和其他基础架构(例如使用 Onion 架构的 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 的构造如下:

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.");
            }
        }

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

4

1 回答 1

0

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

于 2012-07-25T06:59:57.707 回答