Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Register partically closed generic type with Autofac

I have UnitofWork class and it implement IUnitOfWork. I try to register that with Autofac:

var builder = new ContainerBuilder(); builder     .RegisterGeneric(typeof(UnitOfWork<Repository<>,>))     .As(typeof(IUnitOfWork))     .InstancePerDependency(); 

Implementation is:

public class UnitOfWork<T, O> : IUnitOfWork     where T : Repository<O>     where O : BaseEntity { }  public interface IUnitOfWork : IDisposable {     void SaveChanges(); } 

Gives an error "Type expected"

but this one work on another project:

public class Repository<T> : GenericRepository<T>      where T : BaseEntity {     public Repository(IDbContext context) : base(context) { }    }  public abstract class GenericRepository<T>      : IRepository<T>, IQueryable<T> where T : BaseEntity { }  builder     .RegisterGeneric(typeof(Repository<>))     .As(typeof(IRepository<>))     .InstancePerHttpRequest(); 
like image 575
shortcode Avatar asked Mar 05 '13 14:03

shortcode


1 Answers

You cannot have partially opened classes (e.g. with UnitOfWork<Repository<>,> you have specified T but not O) inside a typeof, try it with:

var builder = new ContainerBuilder(); builder     .RegisterGeneric(typeof(UnitOfWork<,>))     .As(typeof(IUnitOfWork))     .InstancePerDependency(); 

The where T : Repository<O> generic constraint will take care of that the first argument should be an Repository<>

But it won't work with RegisterGeneric because it requires a generic interface so need to create a IUnitOfWork<T,O>

But your model is very strange. Why does your UnitOfWork need a Repository<> type argument?

Instead of having it as a type argument you can get an Repository<> in your UnitOfWork<E> constructor:

public class UnitOfWork<E> : IUnitOfWork<E> where E : BaseEntity {     private readonly Repository<E> repository;      public UnitOfWork(Repository<E> repository)     {         this.repository = repository;     }      //.. other methods  } 

Where IUnitOfWork<E>

public interface IUnitOfWork<E> : IDisposable where E : BaseEntity {     void SaveChanges(); } 

And the Autofac registration:

var builder = new ContainerBuilder(); builder     .RegisterGeneric(typeof(Repository<>)).AsSelf(); builder     .RegisterGeneric(typeof(UnitOfWork<>))     .As(typeof(IUnitOfWork<>))     .InstancePerDependency(); var container = builder.Build();  // sample usage var u = container.Resolve<IUnitOfWork<MyEntity>>(); 
like image 154
nemesv Avatar answered Sep 20 '22 20:09

nemesv