简介:-我是编程的新手,我经常使用构造函数注入和工厂模式。这是我第一次使用第三方工具Autofac进行DI。我了解基本知识,但我希望了解一些事情,希望您能提供帮助。
项目设置: N层MVC应用程序(数据,模型,测试,UI项目)(仅在UI项目中安装了NuGet Autofac和Autofac.MVC5)
问题: Autofac是否应该通过NuGet安装在我的N层MVC应用程序中的每个项目中,还是可以在UI项目中安装它?我正在尝试使用Modules,并且好奇是否应该将DataAccessModule放置在Data项目与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;
}
}
问题: 在我的项目中看到“ new ”关键字的任何地方,都应尝试注入这种依赖性吗?例如,在我的存储库中,是SqlConnection还是SqlCommand对象?
您可以提供的任何帮助或指导将不胜感激。我试图执行一个非常基本的示例,以更好地了解如何配置其他组件
提前谢谢!
答案 0 :(得分:0)
在每个要配置依赖项的程序集中,您都需要安装Autofac软件包。我建议将DataBaseModule
与存储库类一起放入程序集。将存储库接口保留在某些高级程序集(如BusinessLayer)中,从DataLayer和UI程序集添加对它的引用,并创建存储库类internal
。因此,您可以将实现隐藏在抽象之后。使DatabaseModule
public
成为唯一一个知道存储库配置的人。考虑使用CompositionRoor pattern并看一下Onion Architecture来理解整个想法。
您注入的连接字符串非常好。您也可以在工厂类中使用相应的接口封装SqlConnection
的创建。然后将IConnectionFactory
注入您的存储库并获得更大的灵活性。通过将数据从数据库映射到对象的方式来研究Dapper。
尽管存储库是无状态的(不包含任何可变字段或属性),但请使用SingleInstance()
策略而不是其他策略。您的存储库现在是无状态的,请使其保持无状态。
您不必用DI模式替换每个new
运算符。仅将其用于“不稳定”依赖项。例如,“ String”和“ Int32”类像石头一样稳定,因此您无需避免使用new
运算符。在您的存储库中,SqlCommand
和SqlDataReader
是稳定的。您将永远不会用SqlCommand
来更改MongoComman
,而是保持SqlDataReader
不变。我想您将更改整个存储库。类RatingRepositoryADO
对于您的应用程序是不稳定的依赖关系,因此您将其隐藏在接口后面并注入到控制器中。看看Mark Seeman book的理论和最佳实践。
希望有帮助。