【问题标题】:MVC 4 Autofac and Generic Repository patternMVC 4 Autofac 和通用存储库模式
【发布时间】:2012-09-05 14:53:19
【问题描述】:

我在我的 MVC 4 应用程序中使用了工作单元和通用存储库模式。我要解决的问题是为系统中的每个实体创建存储库存根。为了利用 Autofac Ioc,我必须为每个实体创建一个存储库类和接口,以便我可以在 Autofac 中注册它。

应用启动...

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

存储库类

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

界面

public interface ISchoolDetailRepository : IRepository<SchoolDetail>
{
}

这似乎是很多额外的工作。

有没有办法注册 Type 的通用存储库而不是创建所有这些空类?

然后在我的服务类中,我可以将泛型类型通过 Ioc 传递给构造函数,例如...

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;
    }
}

容器配置

// 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));

异常来自上面你给我的表达式运行的代码..

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

存储库库

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

}

【问题讨论】:

    标签: c# .net asp.net-mvc dependency-injection autofac


    【解决方案1】:

    您需要 Autofac 的open generics 功能:

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

    然后您完全按照您的描述使用您的存储库:

    public class SomeService
    {
        private readonly IRepository<SomeEntity> _repository;
    
        public SchoolService(IRepository<SomeEntity> repository)
        {
            this._repository= repository;
        }
    }
    

    【讨论】:

    • 我必须对我的实体做些什么才能使其工作?我使用的是 Code First,所以我的实体只是普通的 POCO。我收到一个错误。Entities.SchoolDetail 不是开放的泛型类型定义。
    • 你不需要对你的实体进行 entithing。如果您有RepositoryBase&lt;T&gt; : IRepository&lt;T&gt;,那么您只需将此行添加到您的容器构建器builder.RegisterGeneric(typeof(RepositoryBase&lt;&gt;)) .As(typeof(IRepository&lt;&gt;));,它应该可以工作。您不需要为每个实体都这样做。您能否发布更多代码,实际容器配置的外观以及您从哪里得到异常?
    • 查看更新.. 错误发生在使用 RegisterGeneric 的行的 App_Start 内
    • 您需要完全像这样写:builder.RegisterGeneric(typeof(RepositoryBase&lt;&gt;)) .As(typeof(IRepository&lt;&gt;)); 注意空的&lt;&gt;,它将为您的所有实体注册您的存储库。那么就不需要为你的实体手动创建一个专用的存储库,所以你不需要创建例如SchoolRepositoryISchoolRepository 也可以删除注册。
    • 是的,你的 RepositoryBase&lt;T&gt; 应该实现你的 IRepository&lt;T&gt; 并且不能是 abstract 否则 Autofac 无法创建它。如果您需要一些自定义逻辑,您仍然可以创建/保留您的ISchoolRepositorySchoolRepository,并且您可以像以前一样注册它们。它们将与您的通用产品一起使用。
    猜你喜欢
    • 1970-01-01
    • 2012-05-07
    • 2016-02-12
    • 1970-01-01
    • 1970-01-01
    • 2011-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多