本文介绍了如何正确处理与Autofac注册的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我实现了工作单位/ Repository模式,所描述的这里,但我还使用autofac和构造器注入,所以我注册的UnitOfWork并的DbContext(PsyProfContext)班是这样的:

I've implemented Unit of Work/Repository pattern, as described here, but I'm also using autofac and constructor injection, so I registered UnitOfWork and DbContext (PsyProfContext) class like this:

 builder.Register(context => new PsyProfContext()).InstancePerHttpRequest();
 builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerHttpRequest();

和一切的伟大工程!

除了一件事:我还使用的,我已经实现了这是使用实体框架来写日志进入数据库CustomTraceListener。

Except for one thing: I'm also using enterprise library logging block, and I have implemented CustomTraceListener which is using Entity Framework to write log entry into the database.

我的控制器看起来像这样(它是空的,因为此刻我只是试图验证是否所有的东西(国际奥委会,日志,实体框架)的工作):

My controller looks like this (it is empty because at the moment I just tried to verify if all the things (IoC, logging, entity framework) are working):

public class HomeController : Controller
{
    private readonly UnitOfWork unitOfWork;

    public HomeController(IUnitOfWork unitOfWork)
    {
        this.unitOfWork = (UnitOfWork) unitOfWork;
    }

    //
    // GET: /Home/
    public ActionResult Index()
    {
        throw new HttpException();
        return View();
    }

    protected override void Dispose(bool disposing)
    {
        unitOfWork.Dispose();
        base.Dispose(disposing);
    }
}

而在CustomTraceListener类的Write方法,我试图解决的UnitOfWork:

And in the Write method of the CustomTraceListener class, I've tried to Resolve UnitOfWork:

DependencyResolver.Current.GetService<IUnitOfWork>() as UnitOfWork;

但我得到的是已经部署一个实例!所以我把一些断点,并发现该控制器的Dispose方法是CustomTraceListener类的Write方法之前调用,所以最后我也没发现比使用的DbContext(PsyProfContext)等解决方案,直接道:

But I get an instance which is already disposed! so I've put some breakpoints and found out that Dispose method of the controller is called before the Write method of the CustomTraceListener class, so in the end I didn't found other solution than using DbContext (PsyProfContext) directly:

public override void Write(object o)
    {
        using (var conext = new PsyProfContext())
        {
            var customLogEntry = o as CustomLogEntry;

            if (customLogEntry != null)
            {
                var logEntry = new LogEntry
                                   {
                                       //a bunch of properties
                                   };

                conext.Exceptions.Add(logEntry);
                conext.SaveChanges();
            }
        }
    }

但我不喜欢这个解决方案!什么是如果你直接访问的DbContext对象使用的UnitOfWork并Repository模式的地步。或者什么是在如果在某些情况下,手动创建一个注册的对象在项目中使用DI点。

But I don't like this solution! What's the point to use UnitOfWork and Repository pattern if you access DbContext object directly. Or what's the point in using DI in project if you create a registered object manually in some cases.

所以,我想听听你的意见,关于如何处理这种情况?是我目前实施罚款,或这绝对是错误的,我应该考虑其他的。

So I wanted to hear your opinion, about how to deal with this kind of situations? Is my current implementation fine, or it is definitely wrong and I should think about another one.

任何帮助将大大AP preciated任何想法,欢迎!

Any help will be greatly appreciated and any ideas are welcome!

推荐答案

看起来你可能有一对夫妇的问题。

It looks like you may have a couple of problems.

首先,如果你手工处理工作对象的单位在你的控制器,控制器应采取国有&LT; IUnitOfWork&GT; 在构造函数中。当请求生命周期配置会自动处理任何的IDisposable 组件 - 包括控制器和任何解析的依赖 - 除非你指定了不知何故你要接管的所有权的寿命。

First, if you're manually disposing the unit of work object in your controller, your controller should take an Owned<IUnitOfWork> in the constructor. When the request lifetime is disposed it will automatically dispose of any IDisposable components - including the controller and any resolved dependencies - unless you specify somehow that you're going to take over ownership of the lifetime. You can do that by using Owned<T>.

public class HomeController : Controller
{
  Owned<IUnitOfWork> _uow;
  public HomeController(Owned<IUnitOfWork> uow)
  {
    this._uow = uow;
  }
  protected override void Dispose(bool disposing)
  {
    if(disposing)
    {
      this._uow.Dispose();
    }
    base.Dispose(disposing);
  }
}

(注意在处置未成年人的逻辑修复覆盖有 - 你需要检查的值处理,所以你不要双击处置你的工作单位)

(Note a minor logic fix in the Dispose override there - you need to check the value of disposing so you don't double-dispose your unit of work.)

另外,你可以注册你的工作单位 ExternallyOwned ,像

Alternatively, you could register your units of work as ExternallyOwned, like

builder
  .RegisterType<UnitOfWork>()
  .As<IUnitOfWork>()
  .ExternallyOwned()
  .InstancePerHttpRequest();

ExternallyOwned 也告诉Autofac,你会采取处置的控制权。在这种情况下,你的控制器看起来像它了。 (一般来说,我想只是让Autofac做的工作,但是,没取得所有权,如果我能避免它。)

ExternallyOwned also tells Autofac that you'll take control of disposal. In that case, your controller will look like it does already. (Generally I like to just let Autofac do the work, though, and not take ownership if I can avoid it.)

其实,看东西都设置方式,您可能,如果你让Autofac做处置您能完全避免处置的问题 - 调用 DependencyResolver 将返回一个尚未处置工作的单位,它会好起来的。

In fact, looking at the way things are set up, you might be able to avoid the disposal problem altogether if you let Autofac do the disposal for you - the call to DependencyResolver would return the unit of work that isn't disposed yet and it'd be OK.

如果不解决它......你可能要添加一些细节你的问题。我看到你的控制器使用工作类的单位,但我看不出它会记录什么,况且我看到在使用的工作单元的监听器实现任何事情。

If that doesn't fix it... you may want to add some detail to your question. I see where your controller is using the unit of work class, but I don't see where it logs anything, nor do I see anything in the listener implementation that's using the unit of work.

(另外,在你的问题的第一个评论,在你的控制器,你不应该从 IUnitOfWork 铸造你的服务的构造注意到的UnitOfWork - 这打破了该接口被摆在首位提供抽象)

(Also, as noted in the first comment on your question, in the constructor of your controller you shouldn't be casting your service from IUnitOfWork to UnitOfWork - that's breaking the abstraction that the interface was offering in the first place.)

这篇关于如何正确处理与Autofac注册的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-21 16:15