简体   繁体   中英

Autofac register nested type?

Lets say I have these four types (with constructors).

public class MyDbContext : IDataContextAsync
{
    public class MyDataContext() { }
}

public class UnitOfWork : IUnitOfWorkAsync
{
    public UnitOfWork(IDataContextAsync dataContext)
    {
        _dataContext = dataContext;
    }
}

public class Repository<TEntity> : IRepositoryAsync<TEntity>
{
    public Repository(IDataContextAsync context, IUnitOfWorkAsync unitOfWork)
    { 
        _context = context;
        _unitOfWork = unitOfWork;
    } 
}

public class AccountService : IAccountService
{
    private readonly IUnitOfWorkAsync _uow;
    private readonly IRepositoryAsync<Account> _repository;

    public AccountService(IUnitOfWorkAsync uow, IRepositoryAsync<Account> repository)
    {
        _uow = uow;
        _repository = repository;
    }
}

I try to register them like so in my container (I'm using WCF by the way).

var builder = new ContainerBuilder();
builder.RegisterType<MyDbContext>().As<IDataContextAsync>();
builder.RegisterType<UnitOfWork>().As<IUnitOfWorkAsync>();
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepositoryAsync<>));

builder.RegisterAssemblyTypes(typeof(AccountService).Assembly)
    .Where(t => t.Name.EndsWith("Service"))
    .As(t => t.GetInterfaces().FirstOrDefault(
        i => i.Name == "I" + t.Name));

Container = builder.Build();

It seems the container generated instance of the unitOfWork that is injected to the AccountService is different than the unitOfWork instance created when the repository is instantiated by the container. How do I ensure the repository gets instantiated with the same instance? For example, here is how the objects would normally be instantiated without a container.

var context = new MyDbContext();
_uow = new UnitOfWork(context);
_repository = new Repository<Account>(context, _uow);

AccountService service = new AccountService(_uow, _repository);

As you can see, the _uow , and the _uow parameter the repository is created with are the same instance. That is not the case when Autofac instantiates the objects and I can't seem to figure out how to "tie them together".

By default Autofac scope is per dependency. It means that each time Autofac need to resolve a dependency, it will return a new instance.

If you want to have a common instance per your lifetime or request, you have to register your type using the appropriate scope.

var builder = new ContainerBuilder();
builder.RegisterType<MyDbContext>()
       .As<IDataContextAsync>()
       .InstancePerLifetimeScope();
builder.RegisterType<UnitOfWork>()
       .As<IUnitOfWorkAsync>()
       .InstancePerLifetimeScope();
builder.RegisterGeneric(typeof(Repository<>))
       .As(typeof(IRepositoryAsync<>))
       .InstancePerLifetimeScope();

builder.RegisterAssemblyTypes(typeof(AccountService).Assembly)
       .Where(t => t.Name.EndsWith("Service"))
       .As(t => t.GetInterfaces().FirstOrDefault(i => i.Name == "I" + t.Name))
       .InstancePerLifetimeScope();

Container = builder.Build();

See Instance Scope in Autofac documentation for more information.

By the way, Autofac integration with WCF seems to not support per-request lifetimescope

Due to WCF internals, there is no explicit support in WCF for per-request lifetime dependencies.

http://docs.autofac.org/en/latest/integration/wcf.html

This limitation is related to the fact that WCF has it own instance scope. It is recommended to use InstanceContextMode.PerCall to be sure that WCF ask a new instance of the service for each WCF call. You can use the ServiceBehavior attribute

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class MyService : IMyService
{ }

I read the source code of AutofacInstanceContext.cs and it seems that a new LifetimeScope is created for each WCF call. So you can register your dependency as InstancePerLifetimeScope and it should work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM