IoC-Autofac并使用相同的通用接口注册多个服务



我有一个包含以下类/接口的服务层(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;
}
}

我把自动对焦设置成这样:

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

问题是,当我在控制器中需要使用guy(CategoryService)为空的任何服务方法时:

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

除了这个错误,我是不是做错了什么?我做不到。

我也试过了。

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

尽管这个默认的ctor是你在这里发布问题的原因,但你的设计还有更多——不那么明显的问题:

  • 虽然您可以删除默认构造函数,但要防止有这个基类。基类通常是严重违反单一责任原则的,并且被用来填充交叉关注点或其他实用函数。通过拥有这个基类派生的类型,它们被迫要求依赖关系,而这些依赖关系甚至可能根本不使用。这会使代码复杂化,并使测试复杂化
  • 由于您有IForoChanService<T>接口,使用者不应该依赖于ForoChanServiceBase基类。事实上,和以前的建议一样:这个基类可能根本不应该存在
  • IForoChanService<T>是一个大型的通用方法工具箱,消费者一次只能使用其中的一个或两个方法。这意味着您违反了接口隔离原则
  • IForoChanService<T>实现可能会违反Liskov替换原则,因为有些实现不允许删除实体。这将导致对Delete的调用失败并出现异常,而不是该实体不存在Delete

最新更新