Izz*_*zzy 7 c# dependency-injection asp.net-core-mvc .net-core
我对DI很新,所以我的知识并不是最好的.我目前正在开发Asp.Net Core MVC应用程序.
假设我有一个返回a的DLL DataSet(我可以完全控制这个DLL并可以根据需要更改它).
所以DLL中的代码如下所示:
public class DataStore : IDataStore
{
private readonly IConfiguration _configuration;
public DataStore(IConfiguration configuration)
{
_configuration = configuration;
}
public DataSet GetDataBySP(string spName, SqlParameter[] parameters = null)
{
DataSet ds = new DataSet();
using(var con = new SqlConnection(_configuration.GetConnectionString("conStr")))
{
using(var cmd = new SqlCommand(spName, con))
{
cmd.CommandType = CommandType.StoredProcedure;
if (parameters?.Length > 0)
cmd.Parameters.AddRange(parameters);
con.Open();
using (var da = new SqlDataAdapter(cmd))
{
da.Fill(ds);
}
}
}
return ds;
}
}
Run Code Online (Sandbox Code Playgroud)
现在假设我有一个名为class的类Foo,它只包含两个属性,如下所示:
public interface IFoo
{
Foo GetFooData();
}
public class Foo : IFoo
{
private readonly IDataStore _dataStore;
public int CurrentCount { get; set; }
public int MaxCount { get; set; }
public Foo(DataRow dr)
{
CurrentCount = dr.Field<int>("CurrentCount");
MaxCount = dr.Field<int>("MaxCount");
}
public Foo(IDataStore dataStore)
{
_dataStore = dataStore;
}
}
Run Code Online (Sandbox Code Playgroud)
在Foo我有一个方法GetFooData如下:
public Foo GetFooData()
{
var ds = _dataStore.GetDataBySP("sp name");
//is the below code breaking the DI pattern rule?
return ds.Tables[0].AsEnumberable().Select(f => new Foo(f)).FirstOrDefault();
}
Run Code Online (Sandbox Code Playgroud)
在Startup.csinside ConfigureServices(IServiceCollection services)方法中,我执行以下操作:
services.AddScoped<IFoo, Foo>();
Run Code Online (Sandbox Code Playgroud)
所以我的问题是,通过在new Foo(f)里面做Select()我打破DI模式?如果是的话,您能否就如何克服这个问题提出建议.
我会通过使用存储库和数据传输对象(DTO)解决您的问题,如下所示:
您可以将一些公共接口注入到代码中:
public interface IFooRepository
{
FooDto GetFirst();
}
public interface IDataSetFactory
{
DataSet GetDataSet(string spName, SqlParameter[] = null);
}
Run Code Online (Sandbox Code Playgroud)
一些DTO将数据从一个类传递到另一个类(并且只有数据):
public class FooDto
{
public int CurrentCount { get; set; }
public int MaxCount { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
一些内部实现,隐藏在界面用户眼中:
internal sealed class FooRepository : IFooRepository
{
private readonly IDataSetFactory _dsFactory;
public FooRepository(IDataSetFactory dsFactory)
{
_dsFactory = dsFactory;
}
public FooDto GetFirst()
{
return _dsFactory.GetDataSet("sp name")
.Tables[0]
.AsEnumberable()
.Select(Map)
.FirstOrDefault();
}
private FooDto Map(DataRow dr)
{
return new FooDto
{
CurrentCount = dr.Field<int>("CurrentCount"),
MaxCount = dr.Field<int>("MaxCount")
};
}
}
internal sealed class DataSetFactory : IDataSetFactory
{
public DataSetFactory() { }
private DataSet GetDataSet(string spName, SqlParameter[] = null)
{
//set up sql parameters, open connection
return ds;
}
}
Run Code Online (Sandbox Code Playgroud)
并且给定一些特定的DI框架(Ninject,DryIoc等),您可以将这些接口注入代码中的任何位置.使用DI的巨大好处 - 它迫使您正确设计应用程序(与实现分离的接口),因此在某个时间点您可以实现IFooRepository以从天空中的星星或文件中读取数据,或者返回空导致测试,或任何你想要它做的事情.
如果你设计不正确 - 它可能不会编译,或者会过度复杂.DI的良好使用是一个难题,但估计99%的*.cs文件不会引用任何DI框架引用:
using System.IO;
using Ninject; //<-- I mean, this one. If it is everywhere, something is overcomplexed and you are not using framework correctly.
using System.Media;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
383 次 |
| 最近记录: |