MVC 4 Autofac and Generic Repository pattern

2019-03-18 08:52发布

I am utilizing the Unit Of Work and Generic Repository pattern in my MVC 4 app. The problem I am trying to solve is creating Repository stubs for every entity in my system. In order to utilize the Autofac Ioc I am having to create a repository class and interface for every entity so that I can register it in Autofac.

app start...

builder.RegisterType<SchoolDetailRepository>().As<ISchoolDetailRepository>().InstancePerHttpRequest();

Repository class

 public class SchoolDetailRepository : RepositoryBase<SchoolDetail>, ISchoolDetailRepository
{
    public SchoolDetailRepository(IDatabaseFactory databaseFactory) : base(databaseFactory)
    {
    }
}

Interface

public interface ISchoolDetailRepository : IRepository<SchoolDetail>
{
}

It seems like a lot of extra work.

Is there a way to register the generic repository of Type rather than creating all these empty classes?

Then in my service class I can just have the generic type passed into the constructor via Ioc like...

public class SchoolService : ISchoolService
{
    private readonly IRepository<SchoolDetail> _schoolRepository;
    private readonly IUnitOfWork _unitOfWork;

    public SchoolService(IRepository<SchoolDetail> schoolRepository, IUnitOfWork unitOfWork)
    {
        this._schoolRepository = schoolRepository;
        this._unitOfWork = unitOfWork;
    }
}

Container config

// Autofac iOC
        var builder = new ContainerBuilder();
        // register controllers
        builder.RegisterControllers(Assembly.GetExecutingAssembly());

        // register services
        builder.RegisterType<MembershipService>().As<IMembershipService>().InstancePerHttpRequest();
        builder.RegisterType<SchoolService>().As<ISchoolService>().InstancePerHttpRequest();
        builder.RegisterType<StudentService>().As<IStudentService>().InstancePerHttpRequest();
        builder.RegisterType<ClassRoomService>().As<IClassRoomService>().InstancePerHttpRequest();
        builder.RegisterType<CourseService>().As<ICourseService>().InstancePerHttpRequest();
        builder.RegisterType<SchoolYearService>().As<ISchoolYearService>().InstancePerHttpRequest();
        builder.RegisterType<EnrollmentService>().As<IEnrollmentService>().InstancePerHttpRequest();
        builder.RegisterType<TeacherService>().As<ITeacherService>().InstancePerHttpRequest();

        // register data infrastructure
        builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerHttpRequest();
        builder.RegisterType<DatabaseFactory>().As<IDatabaseFactory>().InstancePerHttpRequest();

        // register repositories
        builder.RegisterType<SchoolRepository>().As<ISchoolRepository>().InstancePerHttpRequest();
        builder.RegisterType<TeacherRepository>().As<ITeacherRepository>().InstancePerHttpRequest();
        builder.RegisterType<MembershipRepository>().As<IMembershipRepository>().InstancePerHttpRequest();
        builder.RegisterType<RoleRepository>().As<IRoleRepository>().InstancePerHttpRequest();
        builder.RegisterType<ProfileRepository>().As<IProfileRepository>().InstancePerHttpRequest();
        builder.RegisterType<UserRepository>().As<IUserRepository>().InstancePerHttpRequest();
        builder.RegisterType<StudentRepository>().As<IStudentRepository>().InstancePerHttpRequest();
        builder.RegisterType<ClassRoomRepository>().As<IClassRoomRepository>().InstancePerHttpRequest();
        builder.RegisterType<CourseRepository>().As<ICourseRepository>().InstancePerHttpRequest();
        builder.RegisterType<EnrollmentRepository>().As<IEnrollmentRepository>().InstancePerHttpRequest();
        builder.RegisterType<SchoolYearRepository>().As<ISchoolYearRepository>().InstancePerHttpRequest();
        builder.RegisterType<GradeLevelRepository>().As<IGradeLevelRepository>().InstancePerHttpRequest();
        //builder.RegisterType<SchoolDetailRepository>().As<ISchoolDetailRepository>().InstancePerHttpRequest();
        builder.RegisterGeneric(typeof(RepositoryBase<SchoolDetail>)).As(typeof(IRepository<SchoolDetail>));

        // build and setup resolver
        IContainer container = builder.Build();
        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

the exception is coming from the above code where the expression you gave me runs..

builder.RegisterGeneric(typeof(RepositoryBase<SchoolDetail>)).As(typeof(IRepository<SchoolDetail>));

RepositoryBase

public abstract class RepositoryBase<T> where T : class
{
private LearningCompactPilotContext _dataContext;
private readonly IDbSet<T> _dbset;
protected RepositoryBase(IDatabaseFactory databaseFactory)
{
    DatabaseFactory = databaseFactory;
    _dbset = DataContext.Set<T>();
}

protected IDatabaseFactory DatabaseFactory
{
    get; private set;
}

protected LearningCompactPilotContext DataContext
{
    get { return _dataContext ?? (_dataContext = DatabaseFactory.Get()); }
}

... more code

}

1条回答
Explosion°爆炸
2楼-- · 2019-03-18 09:21

You need the open generics feature of Autofac:

builder.RegisterGeneric(typeof(RepositoryBase<>))
   .As(typeof(IRepository<>));

Then you use your repositories exactly as you described:

public class SomeService
{
    private readonly IRepository<SomeEntity> _repository;

    public SchoolService(IRepository<SomeEntity> repository)
    {
        this._repository= repository;
    }
}
查看更多
登录 后发表回答