至于为什么不采用简单的三层架构,偏偏采用七层,甚是不理解,不过不理解归不理解,东西还是得照做啊;
《 所谓三层、七层其实核心理念还是没有变的,无非就是划分层次多了,层与层之间的耦合性降低了,也就是多传几次值;不过F(外观)层到现在也是不理解,虽然说是解耦,但是没有体会到它的真正作用,我想应该是我哪里写的有问题,不然怎么会感觉F层和B层写的代码神相似呢,跪求各位大神在评论解释说明下!
当然通过借鉴他人的话语理解就是将外观层写成一个整体,然后B层中的各种类都调用这个外观,剪断U层和B层错综复杂的交互,然而这个整体,迄今为止还不知道该怎么写比较合适? 》
当然本篇博客是优化过的,七层之间传递关系图这里就不细写了,哪里有问题,欢迎指出,万分感谢;
(一)、当然我们得从最底层看起,所以我选择了“U层”,别问我为什么?你都不知道高层要干啥,怎么去底层写代码!
public static string loginName="";
private void btnLogin_Click(object sender, EventArgs e)
{
string name = txtName.Text.Trim();
string pwd = txtPwd.Text.Trim();
string type;
UserFacade uFacade = new UserFacade();
LoginState lState = uFacade.Login(name,pwd,out type);//通过out传递从数据库返回的数据,然后在判断
switch (lState)
{
case LoginState.Ok:
FormMain main = new FormMain();
main.Tag = type;//判断是操作员窗体还是管理员
loginName = name;
main.Show();
this.Hide();
break;
case LoginState.NameError:
MessageBox.Show("用户名错误");
break;
case LoginState.PwdError:
MessageBox.Show("密码错误");
break;
default:
break;
}
}
当然了U层一开始也写不出这么NX的代码的,慢慢摸索出来的,那现在聊聊U层起初写点什么吧;
目的:通过数据库中返回的数据,判断登录是否成功(成功、账号错误、密码错误),如果成功后则,判断登录名的类型,从而展示主窗体;否则返回提示信息(账号或者密码错误)。
这么一说,那到底该怎么写,判断三者是否用select ..case或者if..else if..else语句,那么应该返回什么进行判断呢?其实在参数中通过bool类型转换即可,但是好像需要有三种,不仅仅返回登录成功或者失败,所以这里“增加”了-实体类(Entity):辅助返回值,三种类型
namespace Entity
{
public enum LoginState
{
Ok,
NameError,
PwdError
}
}
(二)、当然真正的关于这一层的实体得写成这个样子-“Entity层”,实体层中一定要写完数据库表中所有的字段,如果有主外键等等在实现功能的时候需要扩充实体层的话,不妨另写一个OtherClass类,“Partial”修饰符能够很好的把本类和OtherClass类无缝结合。
namespace Entity
{
public partial class UserInfo
{
public int UId { get; set; }
public string UName { get; set; }
public string UPwd { get; set; }
public string UType { get; set; }
}
}
(三)、此时也当然也不可能在U层写出上面那些代码,但是知道了高层想要做什么,此时底层还不会写代码吗?-转D层"Dal";
或许有伙伴有疑问了,为什么仅仅返回传递一个name参数,而没有pwd,这里我们想通过账号查找其它信息,所以仅仅有一个参数即可;
public UserInfo GetByName(string name)
{
UserInfo ui = null;
string sql = "select * from userinfo where uname=@name";
SqlParameter p = new SqlParameter("@name", name);
DataTable dt = SqliteHelper.GetDateTable(sql, p);
if (dt.Rows.Count>0)
{
ui = new UserInfo()
{
UId = Convert.ToInt32(dt.Rows[0][0]),
UName = name,
UPwd=dt.Rows[0][2].ToString(),
UType=dt.Rows[0][3].ToString()
};
}
return ui;
}
(四)、那么接下来看看D层需要实现的接口层"IDal"层,声明接口实现方法,让子类去重写,利用反射技术;
namespace IDAL
{
public partial interface UserIDal
{
//List<UserInfo> GetList();
//int Insert(UserInfo ui);
//int Update(UserInfo ui);
//int Delete(int id );
UserInfo GetByName(string name);
}
}
(五)、然后是工厂层“Factory”(采用抽象工厂+反射),外加“配置文件”便于后期更换不同类型的数据库
namespace Factory
{
public partial class DataAccess
{
private static readonly string AssemblyName = ConfigurationManager.AppSettings["Dal"];
//前提D层中“DAL.sqlserver”表名命名的,才方便更换数据库
//private static readonly string middleName = ConfigurationManager.AppSettings["DB"];
public static UserIDal CreateUser()
{
string className = AssemblyName + "." + "UserDal";
return (IDAL.UserIDal)Assembly.Load(AssemblyName).CreateInstance(className);
}
}
}
配置文件<App.config>中信息需要这样写;这里的话,我才用appSettings和ConnectionStrings两种发挥不同的作用,当然有些文章中采用的一种,感觉稍微有些误用了,虽然最终的目的都可以实现。
<configuration>
<appSettings>
<add key="Dal" value="DAL"/>//反射部分需要
<add key="DB" value="Sqlserver"/>//更换不同数据库,只需要改变这里
</appSettings>
<connectionStrings>
<add name="sql" connectionString="server=DESKTOP-GCS3QKO\SQLEXPRESS;uid=sa;pwd=1;database=Charge_sys"/>
</connectionStrings>
(六)、接下来便是B层“BLL”,充分体现了依赖倒转原则:实现依赖于抽象;
namespace BLL
{
public partial class UserBll
{
private UserIDal uIDal;
public UserBll()
{
uIDal = DataAccess.CreateUser();
}
public LoginState Login(string name,string pwd,out string type)
{
type = null;
//根据用户名进行对象查询
UserInfo ui = uIDal.GetByName(name);
if (ui==null)
{
return LoginState.NameError;
}
else
{
if (ui.UPwd.Equals(pwd))
{
type = ui.UType;
return LoginState.Ok;
}
else
{
return LoginState.PwdError;
}
}
}
}
}
(七)、然后是外观层“Facade”-也就是博文开头说的,自己发现没有什么意思+不理解的这一层;
namespace Facade
{
public partial class UserFacade
{
private UserBll uBll;
public UserFacade()
{
uBll = new UserBll();
}
public LoginState Login(string name, string pwd, out string type)
{
type = null;
return uBll.Login(name,pwd,out type);
}
}
}
各位伙伴有没发现,F层、B层实例化其他层的时候,都是通过构造方法实现的,作用要好比于直接私有实例化;
到这里的话,整个七层架构中登录功能也算完成了,不知道各位有没理解和消化,当然立马消化的话,还是有些困难的,当初我也是敲了几个窗体后才消化的,之前仅仅称为理解;希望读者可以在下方留下宝贵的见解,如果感觉好的话,请在博文“右上方点赞”支持小编;