Autofac 模块实现 - 连接字符串
Autofac Module Implementation - Connection String
简介: - 我是编程新手,我经常使用构造函数注入和工厂模式。这将是我第一次使用第三方工具 Autofac 进行 DI。我了解基础知识,但我正在寻求对一些事情的理解,希望你能提供帮助。
项目设置: N 层 MVC 应用程序(数据、模型、测试,UI 项目)(NuGet Autofac 和 Autofac.MVC5 仅安装在 UI 项目)
问题:
Autofac 应该通过 NuGet 安装在我的 N 层 MVC 应用程序中的每个项目中,还是只将它安装在 UI 项目中好吗?我正在试验模块,好奇我的 DataAccessModule 是否应该放在我的数据项目中,而不是 UI 项目。
多部分问题:
我正在尝试将连接字符串注入我的存储库,但我不确定我是否正确执行此操作。存储库根据我的 Web.config 文件中设置的 RepositoryType 值进行注册。我在示例中使用 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;
}
}
- 我在实施我的模块并传入
连接字符串?
- 我是否应该将我的连接分离到一个单独的 class 来实现
具有 GetConnectionString 方法的接口并解析它,以及
将实例范围设置为单个实例而不是我的方式
是吗?
- 存储库应该使用 InstancePerRequest 还是
InstancePerLifetimeScope?我在一些例子中都见过,所以我只是
想知道什么最好用 why/when
问题:
在我的项目中任何地方看到“new”关键字时,我是否应该尝试注入该依赖项?例如,在我的存储库中,SqlConnection 或 SqlCommand 对象?
如果您能提供任何帮助或指导,我们将不胜感激。我尝试执行一个非常基本的示例,以更好地理解如何配置其他组件
提前致谢!
您需要在每个程序集中安装 Autofac 包,并在其中配置依赖项。我建议将 DataBaseModule
放入带有存储库 classes 的程序集中。将存储库接口保留在一些高级程序集中,如 BusinessLayer,从 DataLayer 和 UI 程序集中添加对它的引用,并创建存储库 classes internal
。因此,您可以将您的实现隐藏在抽象之后。 Make DatabaseModule
public
,它应该是唯一一个知道存储库实现的人。考虑 CompositionRoor pattern and take a look on Onion Architecture 以理解整个想法。
你的连接字符串注入非常好。也可以在factory class中封装SqlConnection
的创建,对应接口。然后将 IConnectionFactory
注入您的存储库并获得更大的灵活性。顺便看看 Dapper 将数据从数据库映射到对象。
虽然存储库是无状态的(不包含任何可变字段或属性),但使用 SingleInstance()
策略而不是其他策略。您的存储库现在是无状态的,请保持它们无状态。
您不必用 DI 模式替换每个 new
运算符。仅将其用于 "unstable" 依赖项。例如 classes 'String' 和 'Int32' 稳如磐石,你不需要为他们避免 new
运算符。在您的存储库上下文中,SqlCommand
和 SqlDataReader
是稳定的。您永远不会将 SqlCommand
更改为 MongoComman
,而是保持 SqlDataReader
不变。我想您将更改整个存储库。 Class RatingRepositoryADO
对您的应用程序来说是不稳定的依赖项,因此您将其隐藏在界面后面并注入到控制器中。查看 Mark Seeman book 以了解理论和最佳实践。
希望对您有所帮助。
简介: - 我是编程新手,我经常使用构造函数注入和工厂模式。这将是我第一次使用第三方工具 Autofac 进行 DI。我了解基础知识,但我正在寻求对一些事情的理解,希望你能提供帮助。
项目设置: N 层 MVC 应用程序(数据、模型、测试,UI 项目)(NuGet Autofac 和 Autofac.MVC5 仅安装在 UI 项目)
问题: Autofac 应该通过 NuGet 安装在我的 N 层 MVC 应用程序中的每个项目中,还是只将它安装在 UI 项目中好吗?我正在试验模块,好奇我的 DataAccessModule 是否应该放在我的数据项目中,而不是 UI 项目。
多部分问题: 我正在尝试将连接字符串注入我的存储库,但我不确定我是否正确执行此操作。存储库根据我的 Web.config 文件中设置的 RepositoryType 值进行注册。我在示例中使用 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;
}
}
- 我在实施我的模块并传入 连接字符串?
- 我是否应该将我的连接分离到一个单独的 class 来实现 具有 GetConnectionString 方法的接口并解析它,以及 将实例范围设置为单个实例而不是我的方式 是吗?
- 存储库应该使用 InstancePerRequest 还是 InstancePerLifetimeScope?我在一些例子中都见过,所以我只是 想知道什么最好用 why/when
问题: 在我的项目中任何地方看到“new”关键字时,我是否应该尝试注入该依赖项?例如,在我的存储库中,SqlConnection 或 SqlCommand 对象?
如果您能提供任何帮助或指导,我们将不胜感激。我尝试执行一个非常基本的示例,以更好地理解如何配置其他组件
提前致谢!
您需要在每个程序集中安装 Autofac 包,并在其中配置依赖项。我建议将 DataBaseModule
放入带有存储库 classes 的程序集中。将存储库接口保留在一些高级程序集中,如 BusinessLayer,从 DataLayer 和 UI 程序集中添加对它的引用,并创建存储库 classes internal
。因此,您可以将您的实现隐藏在抽象之后。 Make DatabaseModule
public
,它应该是唯一一个知道存储库实现的人。考虑 CompositionRoor pattern and take a look on Onion Architecture 以理解整个想法。
你的连接字符串注入非常好。也可以在factory class中封装SqlConnection
的创建,对应接口。然后将 IConnectionFactory
注入您的存储库并获得更大的灵活性。顺便看看 Dapper 将数据从数据库映射到对象。
虽然存储库是无状态的(不包含任何可变字段或属性),但使用 SingleInstance()
策略而不是其他策略。您的存储库现在是无状态的,请保持它们无状态。
您不必用 DI 模式替换每个 new
运算符。仅将其用于 "unstable" 依赖项。例如 classes 'String' 和 'Int32' 稳如磐石,你不需要为他们避免 new
运算符。在您的存储库上下文中,SqlCommand
和 SqlDataReader
是稳定的。您永远不会将 SqlCommand
更改为 MongoComman
,而是保持 SqlDataReader
不变。我想您将更改整个存储库。 Class RatingRepositoryADO
对您的应用程序来说是不稳定的依赖项,因此您将其隐藏在界面后面并注入到控制器中。查看 Mark Seeman book 以了解理论和最佳实践。
希望对您有所帮助。