Question

J'écris un site Web ASP.NET MVC, en utilisant autofac pour l'injection de dépendance, et Lightspeed Mindscape comme ORM. Il y a une classe UserRepository, qui dépend d'un UnitOfWork LightSpeed ??et quels services le contrôleur d'ouverture de session.

Problème :. Le UnitOfWork se disposé avant la UserRepository est fini de l'utiliser

  public class UserRepository : IUserRepository
  {
    private readonly BluechipModelUnitOfWork _unitOfWork;

    public UserRepository(BluechipModelUnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork;
    }
    public Principal GetPrincipal(string name)
    {
        // This line throws an ObjectDisposedException - UnitOfWork is already disposed.
        return _unitOfWork.Principals.FirstOrDefault(p => p.Name == name);
    }
    ...

Dans Global.asax, le câblage de la dépendance se fait comme suit:

public class MvcApplication : HttpApplication, IContainerProviderAccessor
{
    private static void RegisterAutofac()
    {
        var builder = new ContainerBuilder();

        // Register the lightspeed context as a singleton
        builder.RegisterInstance(new LightSpeedContext<BluechipModelUnitOfWork>("LightSpeedBluechip"))
            .As<LightSpeedContext<BluechipModelUnitOfWork>>()
            .SingleInstance();

        // Register the unit of work constructor so that a new instance is bound to each HttpRequest
        builder.Register(c => c.Resolve<LightSpeedContext<BluechipModelUnitOfWork>>().CreateUnitOfWork())
            .As<BluechipModelUnitOfWork>()
            .InstancePerLifetimeScope();

        // Register user repository to be one instance per HttpRequest lifetime
        builder.Register(c => new UserRepository(c.Resolve<BluechipModelUnitOfWork>()))
            .As<IUserRepository>()
            .InstancePerLifetimeScope();

        builder.Register(c => new CurrentUserService(
                                  c.Resolve<HttpSessionState>(),
                                  c.Resolve<IUserRepository>(),
                                  c.Resolve<IMembershipService>())
            ).As<ICurrentUserService>()
            .CacheInSession();

        builder.RegisterType<ExtensibleActionInvoker>().As<IActionInvoker>();
        builder.RegisterControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired().InjectActionInvoker();
        builder.RegisterModelBinders(Assembly.GetExecutingAssembly());

        // Set the container provider up with registrations.    
        _containerProvider = new ContainerProvider(builder.Build());

        // Set the controller factory using the container provider.    
        ControllerBuilder.Current.SetControllerFactory(new AutofacControllerFactory(_containerProvider));

Compte tenu des inscriptions ci-dessus, pourquoi autofac être l'élimination UnitOfWork (

Était-ce utile?

La solution

Je suis en mesure de traquer le problème - c'est un Gotcha stupide mais subtile ... J'ai eu une classe CurrentUserService que je me enregistrais comme suit:

    builder.Register(c => new CurrentUserService(
                                  c.Resolve<HttpSessionState>(),
                                  c.Resolve<IUserRepository>(),
                                  c.Resolve<IMembershipService>())
            ).As<ICurrentUserService>()
            .CacheInSession();

Le problème est CacheInSession () , parce que le CurrentUserService dépend de IUserRepository qui autofac a été fidèlement injectait, mais l'élimination de la fin de la première demande.

Cela nous amène à la lumière quelque chose évidente, mais subtile pour être au courant au moment du câblage des injections de dépendance:

Assurez-vous que charge d'ordre supérieur ont toujours la même ou moins vivant que les services dont ils dépendent. Dans mon cas, la solution était de changer le code ci-dessus:

        builder.Register(c => new CurrentUserService(
                                  c.Resolve<HttpSessionState>(),
                                  c.Resolve<IUserRepository>(),
                                  c.Resolve<IMembershipService>())
            ).As<ICurrentUserService>()
            .InstancePerLifetimeScope();

.... qui empêche la CurrentUserService de l'extérieur vivant l'instance dont il dépend.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top