gpt4 book ai didi

c# - 我是否违反了 DI 模式规则

转载 作者:太空狗 更新时间:2023-10-29 18:26:20 25 4
gpt4 key购买 nike

我是 DI 的新手,所以我的知识不是最丰富的。我目前正在开发 Asp.Net Core MVC 应用程序。

假设我有一个返回 DataSet 的 DLL(我可以完全控制这个 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;
}
}

现在假设我有一个名为 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;
}
}

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

Startup.cs 内的 ConfigureServices(IServiceCollection services) 方法中,我执行以下操作:

services.AddScoped<IFoo, Foo>();

所以我的问题是,通过在 Select() 中执行 new Foo(f) 是否破坏了 DI 模式?如果是,您能否就如何克服这个问题提出建议。

最佳答案

我会通过使用存储库数据传输对象 (DTO) 来解决您的问题,如下所示:

您可以将一些公共(public)接口(interface)注入(inject)到您的代码中:

    public interface IFooRepository
{
FooDto GetFirst();
}

public interface IDataSetFactory
{
DataSet GetDataSet(string spName, SqlParameter[] = null);
}

一些 DTO 将数据从一个类传递到另一个类(并且只传递数据):

    public class FooDto
{
public int CurrentCount { get; set; }
public int MaxCount { get; set; }
}

一些内部实现,界面用户看不到:

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

并且给定一些特定的 DI 框架(Ninject、DryIoc 等),您可以将这些接口(interface)注入(inject)代码中的任何位置。使用 DI 的巨大好处 - 它迫使您正确设计您的应用程序(接口(interface)与实现分离),因此在某个时间点您可以实现您的 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;

关于c# - 我是否违反了 DI 模式规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53591051/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com