Внедрение модуля Autofac - строка подключения - PullRequest
0 голосов
/ 30 августа 2018

Intro: - Я новичок в программировании, и я много использовал инжектор конструктора и фабричный шаблон. Я впервые использую сторонний инструмент Autofac для DI. Я понимаю основы, но мне нужно кое-что понять, и я надеюсь, что вы можете помочь.

Настройка проекта: Приложение N-уровня MVC (данные, модели, тесты, проекты пользовательского интерфейса) (NuGet Autofac и Autofac.MVC5 установлены только в проекте пользовательского интерфейса)

Вопрос: Должен ли Autofac быть установлен через NuGet в каждом проекте в моем приложении N-Tier MVC, или это просто в проекте UI? Я экспериментирую с модулями и мне интересно, должен ли мой DataAccessModule быть помещен в мой проект данных против проекта пользовательского интерфейса.

Вопрос из нескольких частей: Я пытаюсь вставить строку подключения в свой репозиторий, и я не уверен, правильно ли я это делаю. Репозитории регистрируются в зависимости от того, какое значение для RepositoryType установлено в моем файле Web.config. Я использую ADO и хранимые процедуры в моем примере. Читая об Autofac.Module, я подумал, что это будет путь.

AutofacConfig

public static class AutofacConfig
{
    public static void RegisterComponents()
    {
        //Autofac - install Autofac and Autofac.MVC5 via NuGet

        //Autofac: create the builder with which components/services are registered.
        var builder = new ContainerBuilder();

        //register all the components that we will use in our container
        //register HomeController as I only have one
        builder.RegisterType<HomeController>().InstancePerRequest();

        //register DataAccessModule
        builder.RegisterModule(new DataAccessModule
        {
            ConnectionString = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString,
            RepositoryType = ConfigurationManager.AppSettings["RepositoryType"].ToString()
        });

        //builds our container
        var container = builder.Build();

        //let ASP.NET MVC know that it should locate services using the AutofacDependencyResolver. This is Autofac’s implementation of the IDependencyResolver interface.
        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
    }

}

DataAccessModule

public class DataAccessModule : Module
{
    public string ConnectionString { get; set; }
    public string RepositoryType { get; set; }

    protected override void Load(ContainerBuilder builder)
    {

        switch (RepositoryType)
        {
            case "ADO":
                builder.RegisterType<DirectorRepositoryADO>().As<IDirectorRepository>().WithParameter("connectionString",ConnectionString).InstancePerRequest();
                builder.RegisterType<DvdDirectorRepositoryADO>().As<IDvdDirectorRepository>().WithParameter("connectionString", ConnectionString).InstancePerRequest();
                builder.RegisterType<DvdRepositoryADO>().As<IDvdRepository>().WithParameter("connectionString", ConnectionString).InstancePerRequest();
                builder.RegisterType<RatingRepositoryADO>().As<IRatingRepository>().WithParameter("connectionString", ConnectionString).InstancePerRequest();
                break;
        }

    }

}

Репозиторий

public class RatingRepositoryADO : IRatingRepository
{
    private readonly string  _connectionString;

    public RatingRepositoryADO(string connectionString)
    {
        _connectionString = connectionString;
    }

    public IEnumerable<Rating> GetAll()
    {
        List<Rating> ratings = new List<Rating>();

        using (var cn = new SqlConnection(_connectionString))
        {
            SqlCommand cmd = new SqlCommand("RatingSelectAll", cn);
            cmd.CommandType = CommandType.StoredProcedure;

            cn.Open();

            using (SqlDataReader dr = cmd.ExecuteReader())
            {
                while (dr.Read())
                {
                    Rating currentRow = new Rating();
                    currentRow.RatingId = (byte)dr["RatingId"];
                    currentRow.RatingName = dr["RatingName"].ToString();

                    ratings.Add(currentRow);
                }
            }
        }

        return ratings;
    }
}
  • Могу ли я узнать, как я реализовал мой модуль и передать Строка подключения?
  • Должен ли я разделить свое соединение на отдельный класс, который реализует интерфейс с методом GetConnectionString и разрешить его и установить область видимости в качестве единственного экземпляра вместо того, как я это?
  • Если хранилища используют InstancePerRequest или InstancePerLifetimeScope? Я видел оба в некоторых примерах, поэтому я просто хотите знать, что лучше всего использовать и почему / когда

Вопрос: В любом месте я вижу ключевое слово " new " в моем проекте, должен ли я попытаться внедрить эту зависимость? Например, в моем репозитории объекты SqlConnection или SqlCommand?

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

Заранее спасибо!

1 Ответ

0 голосов
/ 30 августа 2018

Вам нужен установленный пакет Autofac в каждой сборке, где вы хотите настроить зависимости. Рекомендую поместить DataBaseModule в сборку с классами репозиториев. Сохраните интерфейсы репозитория в некоторой сборке высокого уровня, такой как BusinessLayer, добавьте ссылку на нее из сборок DataLayer и пользовательского интерфейса и сделайте классы репозиториев internal. Таким образом, вы можете скрыть свои реализации за абстракциями. Сделайте DatabaseModule public, это должен быть единственный, кто знает о внедрении репозиториев. Рассмотрим шаблон CompositionRoor и взглянем на Onion Architecture , чтобы понять всю идею.

Ваш ввод строки подключения довольно хорош. Вы также можете инкапсулировать создание SqlConnection в фабричном классе с соответствующим интерфейсом. А затем введите IConnectionFactory в свои репозитории и получите больше гибкости. Взгляните на Dapper , способ отображения данных из БД в объекты.

В то время как хранилища не сохраняют состояния (не содержат никаких изменяемых полей или свойств), используйте политику SingleInstance() вместо других. Ваши репозитории теперь не имеют состояния, сохраняют их без сохранения состояния.

Вам не нужно заменять каждый оператор new на шаблон DI. Используйте его только для «нестабильных» зависимостей. Например, классы String и Int32 стабильны, как скала, вам не нужно избегать оператора new для них. В контексте вашего хранилища SqlCommand и SqlDataReader стабильны. Вы никогда не измените SqlCommand на MongoComman, но сохраните SqlDataReader как есть. Я полагаю, вы измените весь репозиторий. Класс RatingRepositoryADO является нестабильной зависимостью для вашего приложения, поэтому вы прячете его за интерфейс и внедряете в контроллеры. Взгляните на Mark Seeman book для теории и лучших практик.

Надеюсь, это поможет.

...