petshop4.0源代码有十几二十个解决方案,代码之间的关系又是很复杂(对我等菜鸟而言),所以决定从网站首页中间的目录列表开始顺藤摸瓜,往下看。
首页那个目录列表是一个用户控件,控件地址是/web/Controls/NavigationControl.ascx。
ascx页里面用的是一个repeater控件,在里面是一个表格,表格的内容是一个HyperLink控件,HyperLink控件的显示名称和实际链接地址里绑定了数据。
ascx.cs页里,BindCategories() 函数是关键
private void BindCategories() {
Category category = new Category();
repCategories.DataSource = category.GetCategories();
repCategories.DataBind();
}
这里是设置前台页面的repeater控件的数据源。通过Category类的GetCategories返回数据集合。
Category类在/BLL/Category.cs里面定义
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
private static readonly ICategory dal = PetShop.DALFactory.DataAccess.CreateCategory();
public IList < CategoryInfo > GetCategories() {
return dal.GetCategories();
}
}
由此看来,Category类的GetCategories方法实际是通过dal.GetCategories()实现的。
ICategory是一个接口,在/IDAL/ICategory.cs里面定义的
IList < CategoryInfo > GetCategories();
}
接口里定义了一个GetCategories方法,但是这个方法现在只有定义,还没有实现,所以接口dal的GetCategories方法与PetShop.DALFactory.DataAccess.CreateCategory()这个东西有关系。
(这里面有个让我迷糊的东西IList<CategoryInfo>,这个东西像是接口,又像泛型,据说是泛型接口,可为什么当成数据类型返回呢,现在还不太明白,我只是把它当做是一个CategoryInfo类的集合)
PetShop.DALFactory.DataAccess.CreateCategory()明显是在/DALFactory/DataAccess.cs里面定义的。
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
private static readonly string path = ConfigurationManager.AppSettings[ " WebDAL " ];
public static PetShop.IDAL.ICategory CreateCategory() {
string className = path + " .Category " ;
return (PetShop.IDAL.ICategory)Assembly.Load(path).CreateInstance(className);
}
}
这里面关键是Assembly.Load(path).CreateInstance(className)这个函数,这里的意思是创建一个path程序集里面的className这个类的对象。回头想想,也就是说接口dal的GetCategories方法的实现将会在path程序集里面的className类里面实现。
path程序集里面的className类也就是在/SQLServerDAL/Category.cs里面定义的。
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
private const string SQL_SELECT_CATEGORIES = " SELECT CategoryId, Name, Descn FROM Category " ;
public IList < CategoryInfo > GetCategories() {
IList < CategoryInfo > categories = new List < CategoryInfo > ();
using (SqlDataReader rdr = SqlHelper.ExecuteReader(SqlHelper.ConnectionStringLocalTransaction,
CommandType.Text, SQL_SELECT_CATEGORIES, null )) {
while (rdr.Read()) {
CategoryInfo cat = new CategoryInfo(rdr.GetString( 0 ), rdr.GetString( 1 ), rdr.GetString( 2 ));
categories.Add(cat);
}
}
return categories;
}
}
好了,到了这里已经看到熟悉的SQL语句了,说明已经到了底层了,还有一个SqlHelper类也是数据访问层的,放的一些公用的数据访问的代码。
现在思路已经基本清晰了,其它的继续研究......
(ps:接口不就是c++里面的虚基类吗?泛型不就是c++里面的模板吗?)