我正在处理以下代码。我正在处理数据访问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();
}
}
答案 0 :(得分:0)
您应该使用dependency injection,并且对于所需的依赖项,您可以使用构造函数注入,例如:
public class UserBal
{
private readonly IRepositoryDal<User> _userRepositoryDal;
public UserBal(IRepositoryDal<User> userRepositoryDal)
{
_userRepositoryDal = userRepositoryDal
?? throw new ArgumentNullException(nameof(userRepositoryDal));
}
...
}
答案 1 :(得分:0)
依赖注入是最佳选择。以下是您情况的简化示例。
鉴于你的课程可能是这样的:
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>();
...将产生此输出:
DbManager created with parameter "sqlserver?"
现在,我使用了多年前写过的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]
属性的所有调用自动将真实实例包装在此装饰器中。非常适合拦截方法调用以进行调试。