Autofac2とMVC2で問題が発生しています。問題は、ルート依存関係がHttpRequestScopedである一連の依存関係を解決しようとしていることです。UnitOfWork(Disposable)を解決しようとすると、内部ディスポーザがUnitOfWorkオブジェクトをnullの内部廃棄リストに追加しようとしているため、Autofacが失敗します。依存関係を間違ったライフタイムで登録しているのかもしれませんが、運が悪かったので、さまざまな組み合わせを試しました。私が持っている唯一の要件は、MyDataContextがHttpRequest全体にわたって持続することです。
ここにダウンロード用のコードのデモバージョンを投稿しました。
Autofacモジュールはweb.configで設定されます
Global.asax.cs
protected void Application_Start()
{
string connectionString = "something";
var builder = new ContainerBuilder();
builder.Register(c => new MyDataContext(connectionString)).As<IDatabase>().HttpRequestScoped();
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerDependency();
builder.RegisterType<MyService>().As<IMyService>().InstancePerDependency();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
_containerProvider = new ContainerProvider(builder.Build());
IoCHelper.InitializeWith(new AutofacDependencyResolver(_containerProvider.RequestLifetime));
ControllerBuilder.Current.SetControllerFactory(new AutofacControllerFactory(ContainerProvider));
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
}
AutofacDependencyResolver.cs
public class AutofacDependencyResolver
{
private readonly ILifetimeScope _scope;
public AutofacDependencyResolver(ILifetimeScope scope)
{
_scope = scope;
}
public T Resolve<T>()
{
return _scope.Resolve<T>();
}
}
IoCHelper.cs
public static class IoCHelper
{
private static AutofacDependencyResolver _resolver;
public static void InitializeWith(AutofacDependencyResolver resolver)
{
_resolver = resolver;
}
public static T Resolve<T>()
{
return _resolver.Resolve<T>();
}
}
UnitOfWork.cs
public interface IUnitOfWork : IDisposable
{
void Commit();
}
public class UnitOfWork : IUnitOfWork
{
private readonly IDatabase _database;
public UnitOfWork(IDatabase database)
{
_database = database;
}
public static IUnitOfWork Begin()
{
return IoCHelper.Resolve<IUnitOfWork>();
}
public void Commit()
{
System.Diagnostics.Debug.WriteLine("Commiting");
_database.SubmitChanges();
}
public void Dispose()
{
System.Diagnostics.Debug.WriteLine("Disposing");
}
}
MyDataContext.cs
public interface IDatabase
{
void SubmitChanges();
}
public class MyDataContext : IDatabase
{
private readonly string _connectionString;
public MyDataContext(string connectionString)
{
_connectionString = connectionString;
}
public void SubmitChanges()
{
System.Diagnostics.Debug.WriteLine("Submiting Changes");
}
}
MyService.cs
public interface IMyService
{
void Add();
}
public class MyService : IMyService
{
private readonly IDatabase _database;
public MyService(IDatabase database)
{
_database = database;
}
public void Add()
{
// Use _database.
}
}
HomeController.cs
public class HomeController : Controller
{
private readonly IMyService _myService;
public HomeController(IMyService myService)
{
_myService = myService;
}
public ActionResult Index()
{
// NullReferenceException is thrown when trying to
// resolve UnitOfWork here.
// Doesn't always happen on the first attempt.
using(var unitOfWork = UnitOfWork.Begin())
{
_myService.Add();
unitOfWork.Commit();
}
return View();
}
public ActionResult About()
{
return View();
}
}