随笔 - 113  文章 - 0  评论 - 85  阅读 - 54万

PetShop的三层架构介绍.03

    实际项目架构

    如下是一个实际项目架构图形例子:

    图形符号含义,实线+空心三角:代表泛化(据说泛化包含继承和实现)。

                        虚线+空心三角:代表实现,这里我更愿意用"实现符号"代替"泛化符号",下图是我设计时忘了把实线转换成虚线了。

                        虚线+箭头:代表依赖。

   

    .从UI层开始

     一个设定会员号密码的例子:

    UserPwd.aspx.cs(UI层调用BLL层)

复制代码
......
using ReflectionFactory;
using IBLL;
using Model;
using System.Collections.Generic;

public partial class AdminClient_UserPwd : System.Web.UI.Page
{
private static CompanyInfo companyInfo = new CompanyInfo();//实例化实体类对象
private static UserInfo userInfo = new UserInfo();//实例化实体类对象UserInfo
//引用一个企业服务接口,在这里反射工厂(也就是IoC容器)会把企业服务类的实例化对象
//初始化给
该企业服务接口。
private static readonly ICompanyBLL companyBLL = BLLFactory.CreateCompanyBLL();
//同上,这里注入的是一个会员服务类的具体实现。
private static readonly IUserBLL userBLL = BLLFactory.CreateUserBLL();
protected void Page_Load(object sender, EventArgs e){...}

protected void btn_ResetClick(object sender, EventArgs e)
{//调用企业服务
companyBLL的具体方法、会员服务userBLL的具体方法
if (string.IsNullOrEmpty(this.txt_NewPwd.Value)) return;
//按CoID找出 会员号
companyInfo.CoID = Convert.ToInt32(Request.QueryString["CompanyID"]);
IList
<CompanyInfo> companyIL = companyBLL.GetCompany1(companyInfo);
userInfo.UserAccount
= companyIL[0].CoUserAccount;
companyIL.Clear();
//更新该会员号的密码
userInfo.UserPwd = this.txt_NewPwd.Value;
if (userBLL.UpdateUserPwd(userInfo))
{
Page.ClientScript.RegisterClientScriptBlock(
this.GetType(), "",
"alert('修改成功!');window.location.href=location.href;", true); return;
}
}
}
复制代码

 

     .上面例子引出了反射工厂机制

     1.BLLFactory.cs和DALFactory.cs

       BLLFactory.cs:BLL层各个类的反射注入工厂

复制代码
...
using IBLL;

namespace ReflectionFactory
{
/// <summary>业务逻辑层工厂,用于获取相应的业务逻辑层对象</summary>
public sealed class BLLFactory
{
/// <summary>
/// 获取会员模块 逻辑业务层对象
/// </summary>
public static IUserBLL CreateUserBLL()
{
return (IUserBLL)DependencyInjector.GetBLLObject("UserBLL");
}

//更多模块...
...
}
}
复制代码

       DALFactory.cs:DAL层各个类的反射注入工厂

复制代码
...
using IDAL;

namespace ReflectionFactory
{
///<summary>数据访问层工厂,用于获取相应的数据访问层对象</summary>
public sealed class DALFactory
{
/// <summary>
/// 获取会员模块 数据访问层对象
/// </summary>
/// <returns></returns>
public static IUserDAL CreateUserDAL()
{
return (IUserDAL)DependencyInjector.GetDALObject("UserDAL");
}

//更多模块...
...
}
}
复制代码

     2.反射机制=反射+Web.config

       BLLFactory.cs和DALFactory.cs调用DependencyInjector.cs

       DependencyInjector.cs:依赖注入的提供者,使用反射机制实现

复制代码
代码
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.Caching;
using System.Configuration;
using System.Reflection;
using Common;

namespace ReflectionFactory
{
/// <summary>
/// 依赖注入提供者
/// 使用反射机制实现
/// </summary>
public sealed class DependencyInjector
{
/// <summary>
/// 取得数据访问层对象
/// 首先检查缓存中是否存在,如果不存在,则利用反射机制返回对象
/// </summary>
/// <param name="className">数据访问类名称</param>
/// <returns>数据访问层对象</returns>
public static object GetDALObject(string className)
{
///取得数据访问层名称,首先检查缓存,不存在则到配置文件中读取
///缓存依赖项为Web.config文件
object dal = CacheAccess.GetFromCache("DAL");
if (dal == null)
{
CacheDependency fileDependency
= new CacheDependency(
HttpContext.Current.Server.MapPath(
"Web.config"));
dal
= ConfigurationManager.AppSettings["DAL"];
CacheAccess.SaveToCache(
"DAL", dal, fileDependency);
}

///取得数据访问层对象
string dalName = (string)dal;
string fullClassName = dalName + "." + className;
object dalObject = CacheAccess.GetFromCache(className);
if (dalObject == null)
{
CacheDependency fileDependency
= new CacheDependency(
HttpContext.Current.Server.MapPath(
"Web.config"));
dalObject
= Assembly.Load(dalName).CreateInstance(fullClassName);
CacheAccess.SaveToCache(className, dalObject, fileDependency);
}
return dalObject;
}

/// <summary>
/// 取得业务逻辑层对象
/// 首先检查缓存中是否存在,如果不存在,则利用反射机制返回对象
/// </summary>
/// <param name="className">业务逻辑类名称</param>
/// <returns>业务逻辑层对象</returns>
public static object GetBLLObject(string className)
{
///取得业务逻辑层名称,首先检查缓存,不存在则到配置文件中读取
///缓存依赖项为Web.config文件
object bll = CacheAccess.GetFromCache("BLL");
if (bll == null)
{
CacheDependency fileDependency
= new CacheDependency(
HttpContext.Current.Server.MapPath(
"Web.config"));
bll
= ConfigurationManager.AppSettings["BLL"];
CacheAccess.SaveToCache(
"BLL", bll, fileDependency);
}

///取得业务逻辑层对象
string bllName = (string)bll;
string fullClassName = bllName + "." + className;
object bllObject = CacheAccess.GetFromCache(className);
if (bllObject == null)
{
CacheDependency fileDependency
= new CacheDependency(
HttpContext.Current.Server.MapPath(
"Web.config"));
bllObject
= Assembly.Load(bllName).CreateInstance(fullClassName);
CacheAccess.SaveToCache(className, bllObject, fileDependency);
}

return bllObject;
}
}
}
复制代码

      Web.config:UI层配置文件

<configuration>
<appSettings>
<add key="DAL" value="DAL.SOL"/>
<add key="BLL" value="BLL.SOL"/>
</appSettings>
<connectionStrings>

     3.DependencyInjector.cs调用到Common辅助类模块中的CacheAccess.cs类

复制代码
代码
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.Caching;

namespace Common
{
/// <summary>
/// 辅助类,用于缓存操作
/// </summary>
public sealed class CacheAccess
{
/// <summary>
/// 将对象加入到缓存中
/// </summary>
/// <param name="cacheKey">缓存键</param>
/// <param name="cacheObject">缓存对象</param>
/// <param name="dependency">缓存依赖项</param>
public static void SaveToCache(string cacheKey, object cacheObject,
CacheDependency dependency)
{
Cache cache
= HttpRuntime.Cache;
cache.Insert(cacheKey, cacheObject, dependency);
}

/// <summary>
/// 从缓存中取得对象,不存在则返回null
/// </summary>
/// <param name="cacheKey">缓存键</param>
/// <returns>获取的缓存对象</returns>
public static object GetFromCache(string cacheKey)
{
Cache cache
= HttpRuntime.Cache;
return cache[cacheKey];
}
}
}
复制代码

 

    .讲述BLL层的故事

     BLL业务逻辑层模块如何"实现"IBLL接口族模块,且"调用DAL数据访问层模块"?

     UserBLL.cs:BLL层的会员类

复制代码
...
using ReflectionFactory;
using IBLL;
using Model;
using IDAL;
using Common;

namespace BLL
{
public class UserBLL:IUserBLL
{
private static readonly IUserDAL userDAL = DALFactory.CreateUserDAL();

/// <summary>
/// Tb_User更新会员密码
/// </summary>
public bool UpdateUserPwd(UserInfo user)
{
return userDAL.UpdateUserPwd(user);
}

//更多方法...
}
}
复制代码

     IUserBLL.cs:BLL层的会员类接口

复制代码
...
using Model;

namespace IBLL
{
public interface IUserBLL
{
/// <summary>
/// Tb_User更新会员密码
/// </summary>
bool UpdateUserPwd(UserInfo user);

//更多方法...
}
}
复制代码

     IUserDAL.cs:DAL层的会员类接口

复制代码
...
using Model;

namespace IDAL
{
public interface IUserDAL
{
/// <summary>
/// Tb_User更新会员密码
/// </summary>
bool UpdateUserPwd(UserInfo user);

//更多方法...
}
}
复制代码

 

    .DAL层的精彩

复制代码
代码
...
using System.Data;
using System.Data.SqlClient;
using IDAL;
using DBUtility;
using Model;
using Common;

namespace DAL
{
public class UserDAL : IUserDAL
{
private const string SQL_UPDATE_PASSWORD = "UPDATE Tb_User SET UserPwd=@UserPwd WHERE UserAccount=@UserAccount;";
//更多T-SQL语句...

private const string PARM_UserPwd = "@UserPwd";
private const string PARM_UserAccount = "@UserAccount";
//更多参数化查询参数...

/// <summary>
/// Tb_User更新会员密码
/// </summary>
public bool UpdateUserPwd(UserInfo user)
{
SqlParameter[] parms
= new SqlParameter[]{
new SqlParameter(PARM_UserPwd,SqlDbType.VarChar,50),
new SqlParameter(PARM_UserAccount,SqlDbType.VarChar,50)
};
parms[
0].Value = user.UserPwd;
parms[
1].Value = user.UserAccount;
if (SqlHelper.ExecuteNonQuery(SqlHelper.connString, CommandType.Text, SQL_UPDATE_PASSWORD, parms) > 0)
{
return true;
}
else { return false; }
}

//更多方法...
}
}
复制代码

     UserDAL.cs类涉及到"参数化查询"和对"DBUtility类"的调用,DBUtility模块主要就是微软的那个SQLHelper.cs,请自行上网搜索下载。

     这里简述一下参数化查询:

private const string SQL_UPDATE_PASSWORD =
"UPDATE Tb_User SET UserPwd=@UserPwd WHERE UserAccount=@UserAccount;";

    @UserPwd、@UserAccount对应T-SQL语句中的变量;

private const string PARM_UserPwd = "@UserPwd";
private const string PARM_UserAccount = "@UserAccount";

    PARM_UserPwd、PARM_UserAccount是C#中的变量,对应于T-SQL语句中的@UserPwd、@UserAccount;

    在程序中是把变量值传递给@UserPwd、@UserAccount的媒介。

复制代码
 /// <summary>
/// Tb_User更新会员密码
/// </summary>
 public bool UpdateUserPwd(UserInfo user)
{
SqlParameter[] parms
= new SqlParameter[]{
new SqlParameter(PARM_UserPwd,SqlDbType.VarChar,50),
new SqlParameter(PARM_UserAccount,SqlDbType.VarChar,50)
};
parms[
0].Value = user.UserPwd;
parms[
1].Value = user.UserAccount;
if (SqlHelper.ExecuteNonQuery(SqlHelper.connString,
CommandType.Text, SQL_UPDATE_PASSWORD, parms)
> 0)
{
return true;
}
else { return false; }
}
复制代码

     什么是参数化查询?就是把存储过程以T-SQL语句的文本形式执行。

     优点有其二(个人已知的,未知的不探讨):防止T-SQL语句注入攻击;存储过程存在调试难,维护难的情况,参数化查询相对小型、灵活。

     PetShop的三层架构主要篇章到此结束,根据需要会对其中涉及到的一些知识进行补篇。

     PetShop 的三层架构介绍.01

     PetShop 的三层架构介绍.02

     PetShop 的三层架构介绍.03

作者:Star Eyes

欢迎转载,转载请注明:Star-Studio[http://star-studio.cnblogs.com]

 

 

 

posted on   林枫山  阅读(2168)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
< 2010年3月 >
28 1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31 1 2 3
4 5 6 7 8 9 10

点击右上角即可分享
微信分享提示