0

我有一个带有以下类/接口的服务层(IServices 是一个空接口):

 public interface IForoChanService<T> : IService
{
    T GetById(int id);

    IQueryable SearchBy(Expression<Func<T, bool>> predicate);

    IEnumerable<T> GetAll();

    int Create(T entity);

    void CreateMany(IEnumerable<T> entities);

    void Delete(T entity);

    void Delete(int id);

    void DeleteMany(IEnumerable<T> entities);

    void Update(T entity);

}

然后我有一个抽象类一般实现该签名:

    public abstract class ForoChanServiceBase<T> : IForoChanService<T> where T : EntityBase
{
    public T GetById(int id)
     {
         return ChanDbContext.Set<T>().Find(id);
     }
     //all the other methods as well
} 

最后是具体的类:

    public class CategoryService : ForoChanServiceBase<Category>
{

}

我正在尝试使用 AutoFac 在构造函数中注入这些服务(许多:类别、客户端等):我有一个基本控制器:

 public abstract class ForoChanBaseController: Controller
{

    protected ForoChanServiceBase<Post> PostService { get; private set; }
    protected ForoChanServiceBase<Comment> CommentService { get; private set; }
    protected ForoChanServiceBase<Category> CategoryService { get; private set; }

    protected ForoChanBaseController()
    {

    }

    protected ForoChanBaseController(
        ForoChanServiceBase<Post> postService,
        ForoChanServiceBase<Comment> commentService,
        ForoChanServiceBase<Category> categoryService)
    {
        PostService = postService;
        CommentService = commentService;
        CategoryService = categoryService;
    }

}

我正在像这样设置autofac:

        public static void ConfigureIoc()
    {
        var builder = new ContainerBuilder();

        builder.RegisterType<CommentService>().As<ForoChanServiceBase<Comment>>().InstancePerRequest();
        builder.RegisterType<CategoryService>().As<ForoChanServiceBase<Category>>().InstancePerRequest();
        builder.RegisterType<PostService>().As<ForoChanServiceBase<Post>>().InstancePerRequest();

        builder.Build();
    }

问题是我在控制器中需要使用任何服务方法,那个家伙(CategoryService)为空:

        public ActionResult Create()
    {
        var p = new PostFormNewVm
        {
            Categories = CategoryService.GetAll().Select(c => new CategoryVm { Id = c.Id, Title = c.Title })
        };

        return View(p);
    }

除了这个错误,我做错了吗?我不能让它工作。

我也尝试过使用界面。

4

1 回答 1

2

ForoChanBaseController包含多个构造函数,这是一种反模式。由于这个默认构造函数的存在,有一个派生类使用这个构造函数而不是重载的构造函数,这导致依赖项是null.

尽管此默认 ctor 是您在此处发布问题的原因,但您的设计还有更多 - 不太明显的问题:

  • 尽管您可以删除默认构造函数,但请完全避免使用此基类。基类通常违反单一职责原则,要么用于填充横切关注点或其他实用功能。通过让这个基类派生类型被迫要求他们甚至可能根本不使用的依赖项。这会使您的代码复杂化并使测试复杂化。
  • 既然你有IForoChanService<T>接口,消费者不应该依赖于ForoChanServiceBase基类。事实上,与以前相同的建议仍然成立:这个基类可能根本不存在。
  • IForoChanService<T>是一个很大的通用方法工具箱,消费者一次只使用其中一种或两种方法。这意味着您违反了接口隔离原则
  • IForoChanService<T>实现可能会违反Liskov Substitution Principle,因为会有不允许删除实体的实现。这将导致调用Delete失败并出现异常,而不是Delete该实体不存在。
于 2016-12-14T22:11:36.180 回答