2015-01-29 3 views
1

Я передал свой проект уровня предприятия внештатным работникам, и у меня тоже неплохая настройка. Но теперь, когда контракт закончился, и человек также перешел на новую технологию, другими словами, не желая продлевать контракт. Теперь я изучаю этот код на себе. У меня есть 2 3 года опыта работы в C# и MVC. Ниже приведено приблизительное представление о моей архитектуре приложения. Надеюсь, я изо всех сил старался отвлечь архитектурные детали приложения уровня предприятия. Пожалуйста, дайте мне знать, если вам потребуется дополнительная информация по любому из вопросов.Почему я должен использовать тип интерфейса объекта в конструкторе вместо объекта фактического класса


Все мои Entities определяются как классы C# POCO как:

public class Product : BaseEntity 
{ 
    public int ProductId { get; set; } 
    public string ProductName { get; set; } 
} 

Теперь У меня есть IDbContext вроде как:

public interface IDbContext : IDisposable 
{ 
    IDbSet<TEntity> Set<TEntity>() where TEntity : BaseEntity;  
} 

Base Entity представляет собой частичный класс POCO, что каждый Объект POCO наследуется. Вот это класс, который реализует этот IDBContext как:

public class MyObjectContext : DbContext, IDbContext 
{ 
    public new IDbSet<TEntity> Set<TEntity>() where TEntity : BaseEntity 
    { 
     return base.Set<TEntity>(); 
    } 
} 

Теперь я определил IDbContextFactory, который отвечает за обеспечение DBContexts как:

public interface IDbContextFactory 
{ 
    Lazy<IDbContext> CreateDbContext(); 
} 

класс, реализующий этот интерфейс IDBContextFactory оказывает ниже структуры :

public class MyDbContextFactory : IDbContextFactory 
{ 
    public MyDbContextFactory(string dbConnectionString) 
    { 
     _dbConnectionString = Settings.DbConnectionString; 
     _dbContext = CreateDbContext(); 
    } 

    public IDbContext CreateDbContext() 
    { 
     IDbContext dbContext = new IDbContext(() => CreateNewContext()); 
     return dbContext; 
    } 

    private MyObjectContext CreateNewContext() 
    { 
     return new MyObjectContext (_dbConnectionString); 
    } 
} 

Здесь IRepo шаблон входит в роль:

public partial interface IRepository<T> where T : BaseEntity 
{ 
    T GetById(object id); 
} 

Теперь Repository класс, реализующий этот интерфейс, как показано ниже:

public partial class EfRepository<T> : IRepository<T> where T : BaseEntity 
{ 
    private readonly Lazy<IDbContext> _dbContext; 
    private readonly IDbContextFactory _dbContextFactory; 
    private readonly Lazy<ObjectStateManager> _objectStateManager; 

    public EfRepository(IDbContextFactory dbContextFactory) 
    { 
     _dbContextFactory = dbContextFactory; 
     _dbContext= _dbContextFactory.CreateDbContext(); 
     _objectStateManager= new Lazy<ObjectStateManager>(() => ((IObjectContextAdapter)_dbContext.Value).ObjectContext.ObjectStateManager); 
    } 

    public T GetById(object id) 
    { 
     return this.Entities.Find(id); 
    } 
} 

До сих пор мы закончили с настройкой уровня инфраструктуры для управления доступом БД. Теперь дело в том, чтобы использовать эту установку в контроллерах (как у меня прямой доступ Хранилища из контроллеров) как показано ниже:

public class CountryController: BaseController 
{ 
    private readonly Lazy<IRepository<Country>> _countryRepository; 

    public CountryController(Lazy<IRepository<Country>> countryRepository) 
    { 
     _countryRepository = countryRepository; 
    } 

    public Country GetCountryById(int id) 
    { 
     Country country = _countryRepository.Value.GetById(id); 

     if (country != null) 
      return country; 
     else 
      return null; 
    } 

Надеюсь, все выше ясно. Теперь вот некоторые вопросы, которые мне нужно ответить:

1) Почему мы имеем этот слоистый поток, как, как:

IDBContext -> IDBContextFactory -> IRepository <T> 

, а затем, наконец, с помощью этого IRepository в контроллерах для доступа к объектам данных. Иными словами, почему мы полагаемся на интерфейсы вместо фактических объектов класса при внедрении инжекции конструктора для контроллера страны?

2) Является ли это правильным подходом для приложения уровня предприятия, поскольку он должен быть значительно масштабируемым для будущей цели. Если есть кто-то другой, я был бы рад узнать об этом?

3) В конструкторе контроллера я использовал Lazy>, поэтому в чем цель этого Lazy и действительно ли это полезно. Если да, то каким образом?

+1

Надеюсь, это даст вам некоторую идею: http://stackoverflow.com/questions/2026054/why-do-we-use-interface-is-it-only-for-standardization –

+0

Выберете из полки UML-архитектуру диаграммы и проектный документ, который вы подписали с вашим субподрядчиком – xmojmr

+0

Удалите 'Lazy ' из ваших репозиториев-инъекций. Это необязательно и не должно быть частью вашего «контракта». Вы всегда можете использовать прокси-класс, который добавляет ленивость. – Maarten

ответ

3

Это шаблон дизайна.И это называется Инъекция зависимостей.

EfRepository класс требует его зависимости вводить с помощью его конструктор-это известно как конструктор инъекции. Мы также могли бы позволить вводить зависимости через государственную собственность, , известный как инжектор сеттера.

Одна из наиболее важных особенностей шаблона MVC заключается в том, что он позволяет разделять проблемы. Мы хотим, чтобы компоненты нашего приложения до были как можно более независимыми и имели как можно меньше взаимозависимостей как , которыми мы можем управлять.

В нашей идеальной ситуации каждый компонент ничего не знает о каком-либо другом компоненте и имеет дело только с другими областями приложения через абстрактные интерфейсы . Это называется муфтой, и это делает более простым и легким в применении. Интерфейсы помогают нам компоненты развязки.

Нам нужен способ получить объекты, реализующие данный интерфейс , без необходимости создания объекта реализации напрямую. Решение этой проблемы называется зависимая инъекция (DI), , также известная как Инверсия управления (IoC).

DI - это шаблон дизайна, который дополняет свободное соединение, которое мы начали с , добавляя интерфейс.

Котировки копируются из 3-й главы this книга.

+0

Привет, Фархад, Спасибо за ваш ценный ответ. Я получил информацию о DI и Design Pattern. Теперь вы могли бы рассказать мне, какой будет недостаток, если я использую ссылку Direct Class вместо интерфейса вместо интерфейса в инжекции конструктора? – Amy

+0

@Amy Рад помочь. вы когда-нибудь использовали UnitTesting? Например, это увеличит тестируемость вашего приложения. Плотно связанная архитектура не подходит для модульного тестирования. И опять же, главное - разобраться в проблемах. Я действительно рекомендую вам прочитать главы 3 и 6 из книги, в которой я дал ссылку в ответ. Вы узнаете, как использовать Ninject и Moq. –

+0

Спасибо, помощник! Я ценю ваше сотрудничество. Я просматриваю предлагаемые главы. До встречи ! – Amy

Смежные вопросы