私は、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 = Ioc.Container.Get<SPPresenter>(new Ninject.Parameters.ConstructorArgument("view", this));
私はまだパラメーターの Ninject 参照に依存しています。インターフェイスで多くのメソッドをマッピングする以外に、これを抽象化する方法はありますか? 引数に単純な型を渡すことはできませんか?
インジェクション自体はうまく機能しますが、SharePoint タイマー ジョブなどの外部プロセスを使用するときに問題が発生します。ここから ioc コンテナーを再利用するのは明らかにひどい考えなので、依存関係自体をブートストラップする必要があります。さらに、管理 Web アプリケーションではなく、Web アプリケーション プールから構成を読み込む必要があります。それ以外の場合、ジョブはアプリケーション サーバー上でのみ実行できます。このように、ジョブは任意の Web サーバーで実行でき、SharePoint 機能は構成などを Web アプリケーションにデプロイするだけで済みます。
タイマー ジョブの execute メソッドは、関連する 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.");
}
}
これではタイマー ジョブの堅牢性が十分ではなく、ボイラー プレート コードがたくさんあります。私の質問は、このデザインを改善するにはどうすればよいですか? これは最も洗練された方法ではありません。タイマー ジョブの操作コードを抽象化し、タイマー ジョブごとに依存関係を注入する方法を探しています。これが良いアプローチだと思われる場合は、コメントをお聞きしたいと思います。または、誰かがこのような同様の問題に直面した場合はどうなりますか? ありがとう