C# 将业务层类更改为松散耦合

C# 将业务层类更改为松散耦合,c#,C#,我有下面的代码,我正在工作。我正在研究adon.net层的数据访问。我的业务层类UserBAL有问题。问题是我正在UserBAL的构造函数中创建dal和dbmanager的实例。对于UserBAL,如何将其更改为松散耦合?希望你明白我的意思 public interface IEntity { int Id { get; set; } int DoSomething(string one, int two); } public class User : IEntity {

我有下面的代码,我正在工作。我正在研究adon.net层的数据访问。我的业务层类
UserBAL
有问题。问题是我正在
UserBAL
的构造函数中创建dal和dbmanager的实例。对于
UserBAL
,如何将其更改为松散耦合?希望你明白我的意思

public interface IEntity
{
    int Id { get; set; }
    int DoSomething(string one, int two);
}

public class User : IEntity
{
    public int Id { get; set; }
    public int DoSomething(string one, int two)
    {
        throw new NotImplementedException();
    }

    public string Firstname { get; set; }
    public string Lastname { get; set; }
    public string Email { get; set; }
    public string Password { get; set; }
}

public class UserBal //busines logic
{
    private readonly IRepositoryDal<User> _userRepositoryDal;

    public UserBal()
    {
        _userRepositoryDal  = new UserRepositoryDal(new DbManager("sqlserver?"));
    }

    public IEnumerable<User> SearchByName(string name)
    {
        return _userRepositoryDal.SearchByName(name);
    }
}

interface IRepositoryDal<T> where T : IEntity
{
    IEnumerable<T> SearchByName(string username);
    T SearchById(string id);
    void Update(T entity);
    void Remove(T entity);
    void Add(T entity);
}

public class UserRepositoryDal: IRepositoryDal<User>
{
    private readonly IDbManager _dbManager;

    public UserRepositoryDal(IDbManager dbManager)
    {
        //read from either singleton or configuration file !!
        _dbManager = dbManager;
    }
    public IEnumerable<User> SearchByName(string username)
    {                                  
            var parameters = new List<IDbDataParameter>
            {
                _dbManager.CreateParameter("@FirstName", 50, username, DbType.String),
            };

        var userDataTable = _dbManager.GetDataTable("storedpr2",
            CommandType.StoredProcedure, parameters.ToArray());

        foreach (DataRow dr in userDataTable.Rows)
        {
            var user = new User
            {
                Id = int.Parse(dr["Id"].ToString()),
                Firstname = dr["Firstname"].ToString(),
                Lastname = dr["LastName"].ToString(),
                Email = dr["Email"].ToString()
            };

            yield return user;
        }

    }
    public User SearchById(string id)
    {
        var parameters = new List<IDbDataParameter>
        {
            _dbManager.CreateParameter("@Id", 50, id, DbType.Int32),
        };

        var userDataTable = _dbManager.GetDataTable("storedpr2",
            CommandType.StoredProcedure, parameters.ToArray());

        return new User
        {
            Id = int.Parse(userDataTable.Rows[0]["Id"].ToString()),
            Firstname = userDataTable.Rows[0]["Firstname"].ToString(),
            Lastname = userDataTable.Rows[0]["LastName"].ToString(),
            Email = userDataTable.Rows[0]["Email"].ToString()
        };
    }

    public void Update(User entity)
    {
        throw new System.NotImplementedException();
    }

    public void Remove(User entity)
    {
        throw new System.NotImplementedException();
    }

    public void Add(User entity)
    {
        throw new System.NotImplementedException();
    }
}

public partial class FrmLogin : Form
{
    private readonly UserBal _userBal;

    public FrmLogin()
    {
        InitializeComponent();
         _userBal = new UserBal();
    }
}
公共接口的可扩展性
{
int Id{get;set;}
int DoSomething(字符串一,int二);
}
公共类用户:IEntity
{
公共int Id{get;set;}
公共整数DoSomething(字符串一,整数二)
{
抛出新的NotImplementedException();
}
公共字符串名{get;set;}
公共字符串Lastname{get;set;}
公共字符串电子邮件{get;set;}
公共字符串密码{get;set;}
}
公共类UserBal//业务逻辑
{
私有只读IRepositoryDal _userRepositoryDal;
公共用户bal()
{
_userRepositoryDal=newuserrepositorydal(newdbmanager(“sqlserver?”));
}
公共IEnumerable SearchByName(字符串名称)
{
返回_userRepositoryDal.SearchByName(名称);
}
}
接口IRepositoryDal,其中T:Entity
{
IEnumerable SearchByName(字符串用户名);
T SearchById(字符串id);
无效更新(T实体);
无效删除(T实体);
无效添加(T实体);
}
公共类UserRepositoryDal:IRepositoryDal
{
专用只读IDbManager _dbManager;
公共用户RepositoryDal(IDbManager dbManager)
{
//从单例或配置文件读取!!
_dbManager=dbManager;
}
公共IEnumerable SearchByName(字符串用户名)
{                                  
var参数=新列表
{
_dbManager.CreateParameter(“@FirstName”,50,用户名,DbType.String),
};
var userDataTable=_dbManager.GetDataTable(“storedpr2”,
CommandType.StoredProcess,parameters.ToArray());
foreach(userDataTable.Rows中的DataRow dr)
{
var user=新用户
{
Id=int.Parse(dr[“Id”].ToString()),
Firstname=dr[“Firstname”].ToString(),
Lastname=dr[“Lastname”].ToString(),
Email=dr[“Email”].ToString()
};
用户收益率;
}
}
公共用户SearchById(字符串id)
{
var参数=新列表
{
_dbManager.CreateParameter(“@Id”,50,Id,DbType.Int32),
};
var userDataTable=_dbManager.GetDataTable(“storedpr2”,
CommandType.StoredProcess,parameters.ToArray());
返回新用户
{
Id=int.Parse(userDataTable.Rows[0][“Id”].ToString()),
Firstname=userDataTable.Rows[0][“Firstname”].ToString(),
Lastname=userDataTable.Rows[0][“Lastname”].ToString(),
Email=userDataTable.Rows[0][“Email”].ToString()
};
}
公共无效更新(用户实体)
{
抛出新系统。NotImplementedException();
}
公共作废删除(用户实体)
{
抛出新系统。NotImplementedException();
}
公共作废添加(用户实体)
{
抛出新系统。NotImplementedException();
}
}
公共部分类FrmLogin:表单
{
私有只读UserBal\u UserBal;
公共FrmLogin()
{
初始化组件();
_userBal=新的userBal();
}
}
您应该使用,对于所需的依赖项,您可以使用构造函数注入,例如:

public class UserBal
{
    private readonly IRepositoryDal<User> _userRepositoryDal;

    public UserBal(IRepositoryDal<User> userRepositoryDal)
    {
        _userRepositoryDal = userRepositoryDal 
          ?? throw new ArgumentNullException(nameof(userRepositoryDal));
    }

    ...
}
公共类UserBal
{
私有只读IRepositoryDal _userRepositoryDal;
public UserBal(IRepositoryDal userRepositoryDal)
{
_userRepositoryDal=userRepositoryDal
?抛出新ArgumentNullException(nameof(userRepositoryDal));
}
...
}

依赖项注入是一条出路。下面是一个简单的例子

考虑到你的课程可能是这样的:

public interface IEntity { }
public interface IRepositoryDal<T> where T : IEntity { }
public interface IDbManager { }

public class User : IEntity { }

public class UserBal //busines logic
{
    [Injectivity.Attributes.Inject]
    private IRepositoryDal<User> _userRepositoryDal;
}

public class UserRepositoryDal: IRepositoryDal<User>
{
    [Injectivity.Attributes.Inject]
    private IDbManager _dbManager;
}

public class DbManager : IDbManager
{
    [Injectivity.Attributes.Construct()]
    public DbManager([Injectivity.Attributes.Key("dbKey", typeof(string))] string x)
    {
        Console.WriteLine($"DbManager created with parameter \"{x}\"");
    }
}
context.SetDecorator<IRepositoryDal<User>, UserRepositoryDalDecorator>();

这将导致对
context.Resolve()
[Inject]
属性的所有调用自动将实际实例包装在此装饰器中。非常适合拦截用于调试目的的方法调用。

您在此处寻找依赖项注入。在构造
UserBal
时,您会传递一个实例,即
newuserbal(newuserrepositorydal(new DbManager(“sqlserver”))您也可以考虑使用IOC容器来管理这些依赖项,例如Autofac - .jimyjimm,然后您必须设置AutoFac并将其与您的APP集成。不确定,但问题是:“新UserBal(新UserRepositoryDal(新DbMeCerver(SQLServer?))”因为我首先从表示层传递新的UserRepositoryDal。表示层不应该不知道这个对象吗?DbManager也从表示层传递。据我所知,从那一点开始,应该只知道UserBal。你继续这个模式,所以表示层注入了一个
UserBal
,因此不需要知道它是如何构造的。所有连接都发生在应用程序的组成根中。我建议您阅读.NET中的依赖项注入。@devdigital您能解释一下吗?我仍然需要从表示层这样称呼它吗?:new UserBal(new UserRepositoryDal)(new DbManager(“sqlserver?”)是否可以在没有属性的情况下更改它?例如IoC容器?@JimmyJimm-这是一个IoC容器的示例。它只是碰巧使用属性来简化注册。我确实将其设置为允许通过代码注册(如我的问题中所示)。这只关系到类的注册需要如何工作。属性使您可以轻松注册整个程序集,从而在运行时交换程序集。 DbManager created with parameter "sqlserver?"
context.SetDecorator<IRepositoryDal<User>, UserRepositoryDalDecorator>();