【发布时间】:2012-07-21 08:58:39
【问题描述】:
我已经使用 Ninject 依赖注入和其他基础架构(例如 NLog 日志记录等)使用 Onion 架构成功实施了企业 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 应用程序池加载配置,而不是从 admin 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.");
}
}
这不会使计时器作业足够健壮,并且有很多样板代码。我的问题是如何改进这个设计?这不是最优雅的,我正在寻找一种方法来抽象计时器作业操作代码并为每个计时器作业注入它的依赖项。如果您认为这是一个好方法,我只想听听您的 cmets。或者如果有人遇到过类似的问题?谢谢
【问题讨论】:
标签: sharepoint dependency-injection web-config ninject nlog