0

简介: - 我是编程新手,我经常使用构造函数注入和工厂模式。这将是我第一次为 DI 使用第三方工具 Autofac。我了解基础知识,但我正在寻找对一些事情的理解,希望您能提供帮助。

项目设置: N-Tier MVC 应用程序(数据、模型、测试、UI 项目)(NuGet Autofac 和 Autofac.MVC5 仅安装在 UI 项目中)

问题: Autofac 应该通过 NuGet 安装在我的 N-Tier MVC 应用程序中的每个项目中,还是只是在 UI 项目中安装它好吗?我正在试验 Modules 并好奇我的 DataAccessModule 是否应该放在我的 Data 项目和 UI 项目中。

多部分问题: 我正在尝试将连接字符串注入我的存储库,但我不确定我是否正确执行此操作。根据在我的 Web.config 文件中设置的 RepositoryType 值注册存储库。我在示例中使用 ADO 和存储过程。阅读有关 Autofac.Module 的信息,我认为这是要走的路。

自动配置

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

}

数据存取模块

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 对象?

您可以提供的任何帮助或指导将不胜感激。我尝试执行一个非常基本的示例,以更好地了解如何配置其他组件

先感谢您!

4

1 回答 1

0

您需要在每个要配置依赖项的程序集中安装 Autofac 包。我建议DataBaseModule与存储库类一起组装。将存储库接口保留在 BusinessLayer 等高级程序集中,从 DataLayer 和 UI 程序集中添加对它的引用,并创建存储库类internal。因此,您可以将实现隐藏在抽象后面。Make DatabaseModule public,它应该是唯一一个知道存储库实现的人。考虑CompositionRoor 模式并查看Onion Architecture以了解整个想法。

您注入的连接字符串非常好。您还可以SqlConnection使用相应的接口封装在工厂类中的创建。然后注入IConnectionFactory您的存储库并获得更大的灵活性。顺便看看Dapper将数据从 DB 映射到对象。

虽然存储库是无状态的(不包含任何可变字段或属性),但使用SingleInstance()策略而不是其他策略。您的存储库现在是无状态的,请保持无状态。

您不必new用 DI 模式替换每个运算符。仅将其用于“不稳定”依赖项。例如类 'String' 和 'Int32' 像石头一样稳定,你不需要new为它们避免操作符。在您的存储库的上下文中SqlCommand并且SqlDataReader是稳定的。你永远不会改变SqlCommandMongoComman但保持SqlDataReader原样。我想您将更改整个存储库。类RatingRepositoryADO对于你的应用来说是不稳定的依赖,所以你把它隐藏在接口后面并注入到控制器中。看看Mark Seeman 的书,了解理论和最佳实践。

希望能帮助到你。

于 2018-08-30T04:05:18.977 回答