0

у меня есть сервисный слой со следующими классами/intefaces (IServices является пустой интерфейс):IoC - Autofac и зарегистрировать несколько услуг с тем же родовым интерфейсом

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

Кроме s эта ошибка делает я делаю что-то неправильно? Я не могу заставить его работать.

Я пробовал с inteface также.

+1

Ваша проблема в конструкторе по умолчанию, защищенном ForoChanBaseController() {}. Удалите его, и он должен работать. Возможно, вам придется исправить свой класс, где вы используете этот контроллер «ForoChanBaseController». – Prashant

ответ

2

Ваш ForoChanBaseController содержит несколько конструкторов, которые is an anti-pattern. Из-за существования этого конструктора по умолчанию существует производный класс, который использует этот конструктор вместо перегруженного, который вызывает зависимости null.

Хотя по умолчанию т е р и является причиной для Вас, чтобы разместить вопрос здесь, есть более -Меньше очевидно problems- с вашим дизайном:

  • Хотя вы можете удалить конструктор по умолчанию, предотвратить имеющие этот базовый класс вообще. Базовые классы часто являются крупными нарушениями принципа единоличной ответственности и используются либо для решения сквозных задач, либо для других функций полезности. Благодаря тому, что производные типы базового класса вынуждены требовать зависимости, которые они могут даже не использовать вообще. Это усложняет ваш код и усложняет тестирование.
  • Поскольку у вас есть интерфейс IForoChanService<T>, потребители не должны зависеть от базового класса ForoChanServiceBase. На самом деле, тот же совет, что и раньше, имеет место: этот базовый класс, вероятно, вообще не существует.
  • IForoChanService<T> - это большой универсальный ящик для инструментов, в котором потребители используют только один или два из этих методов за раз. Это значит, что вы нарушаете Interface Segregation Principle.
  • IForoChanService<T> реализации могут нарушать Liskov Substitution Principle, поскольку будут реализованы реализации, которые не позволяют удалять объекты. Это вызовет вызов Delete с ошибкой с исключением, вместо Delete, чтобы не существовать для этого объекта.
+0

Большое спасибо за ваши добрые наблюдения.Мой вопрос: должен ли я удалить базовый класс, реализующий общие методы , и непосредственно реализовать интерфейс в каждом классе? Разве я не повторяюсь там? Какая рекомендуемая практика? – MRFerocius