我是否违反了DI模式规则

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模式?如果是的话,您能否就如何克服这个问题提出建议.

eoc*_*ron 7

我会通过使用存储库数据传输对象(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)