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

  • 本文关键字:耦合 业务 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
{
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();
}
}

你应该使用依赖注入,对于所需的依赖,你可以使用构造函数注入,例如:

public class UserBal
{
private readonly IRepositoryDal<User> _userRepositoryDal;
public UserBal(IRepositoryDal<User> userRepositoryDal)
{
_userRepositoryDal = userRepositoryDal 
?? throw new 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}"");
}
}

。那么这段代码:

var context = Injectivity.Context.CreateRoot();
context.SetConfig<string>("dbKey", "sqlserver?");
context.SetFactory<IDbManager, DbManager>();
context.SetFactory<IRepositoryDal<User>, UserRepositoryDal>();
context.SetFactory<UserBal, UserBal>();
var user = context.Resolve<UserBal>();

。将产生以下输出:

使用参数"sqlserver?" 创建的 DbManager?

现在,我使用了几年前编写的 DI 容器。它非常灵活。

因此,对context.Resolve<UserBal>();的调用沿着链运行,查看需要注入哪些内容来创建所有对象的所有实例。最终,创建UserBal需要创建DbManager,从而需要输出。

通常不会显式注册每个工厂。通常,您会将属性放在要注册的所有类上,然后使用context.Register(Assembly.LoadFrom("My.DLL"));或创建一个 XML 配置文件并调用context.LoadConfig(XDocument.Load("config.xml"));

您甚至可以执行以下操作:

context.SetDecorator<IRepositoryDal<User>, UserRepositoryDalDecorator>();

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

最新更新