泛型约束学习总结

Post on by michaelyin

最近在学习代码的时候发现对泛型约束不是很了解,花时间在网上学习了下,现在在这里做个总结吧。

泛型约束主要就是用于在泛型类中对于泛型类所接受的参数的某些特性进行设置。先来说说为什么要使用泛型约束吧。打个比方,一个泛型基类中的某个方法的实现需要调用参数类型生成的实例的Compare方法,但是参数类型不是我们所能够控制的,我们需要在程序编译的时候加入对参数类型的检查,这个时候就要用到泛型约束了。

泛型约束基本上有五种:

  • 值类型约束:要求泛型参数必须是值类型,例如int,short以及自定义的stuct等

public class MyClass2
where T : struct//这个泛型类只接受值类型的泛型参数
{
}

  • 引用类型约束:要求泛型参数必须是引用类型,例如string,object,以及自定义的class

public class MyClass
where T:class//这个泛型类只接受引用类型的泛型参数
{
}

  • 构造函数约束:要求泛型参数必须有构造函数

public class MyClass3
where T : new()
{
}

  • 接口约束:要求泛型参数必须实现某个接口

public class MyClass4
where T : System.IComparable
{
}

  • 基类约束:要求泛型参数必须继承某个基类

public class MyClass5
where T : Customer
{
}

BlogEngine中的BusinessBase泛型基类就使用到了泛型基类,下面我贴上代码

public abstract class BusinessBase<TYPE, KEY> : IDataErrorInfo ...

Bugnet学习总结(7)杂

Post on by michaelyin

Bugnet使用Log4net进行日志记录,Config文件夹下面是配置文件。Global.asax文件里面指明了配置文件的路径。基本的使用网上有相关的资料,自己查下基本就可以弄懂。不过我在这里是想说的是我在使用过程中遇到的一个问题。

Bugnet中的Log的数据源是数据库中的Log表,在使用过程中我发现有时候有些需要被Log的数据并没有被写入到数据库中,有的时候是没有被立即写入到数据库中。我后来在另外的一个小项目中也使用了Log4net,我在Application_Start事件中写入了记录事件,系统进入后马上进入数据库进行查看,但是数据库中的表中病没有那一条表记录。后来我又在里面把数据源加入了生成txt文件,代码就动了下log4net的配置文件,但是每次改变txt文件都能记录下来,大家又兴趣可以试下,如果知道答案的麻烦请告诉我,谢谢了。。。

Log4net学习指南

Bugnet中的rss输出使用的是Rss.net,代码不是很难,有兴趣可以自己去研究下。。

在此之前对于单元测试只是知道,对于如何实施并不是很清楚,在Bugnet里面刚好有机会看看别人如何进行单元测试,草草的看了下,发现只是简单的测试了几个类的功能,不过对于像了解单元测试的朋友来说基本上足够了。。。


Bugnet学习总结(6)用户控件

Post on by michaelyin

用户控件作为Asp.net提供的一种自定义可重用的机制,在很多的项目中都得到了应用,Bugnet里面也使用了很多用户控件。

UserControls文件夹里面放的除了fckeditor和xslt外,就是项目里面要用到的用户控件了,代码都不难,下面就把里面的DisplayBugs.ascx拿出来稍微讲一下。该控件在Bugnet中被用到的次数还是很多的,功能也比较简单,就是提供了一个有图表显示,有排序功能的列表。该用户控件是在Gridview的基础上做的开发,增加了一个BugCollection和EventHandler。BugCollection是Gridview需要绑定的数据源,而EventHandler则是使用了事件。调用该事件实现绑定数据的具体操作。

 <uc1:DisplayBugs ID="InProgressBugs" HeaderBackColor="#eeeeee" CssClass="issues" OnRebindCommand="DisplayBugs_DataBind" runat="server" />

上面是在MyBugs.aspx中重用DisplayBugs.ascx用户控件的代码,可以看到一行代码基本就搞定,而后台的代码只需要把相应的数据源给用户控件,然后执行DataBind就可以了。像这样

BugsAssigned.DataSource = Bug.GetBugsByCriteria(-1, -1, -1, 0, 0, 0, User.Identity.Name, 0, string.Empty, false);
BugsAssigned.DataBind();

需要在这里提到的一点是在这里Gridview绑定数据使用的是自带的分页,其实现的机制是将数据首先全部从数据库中查出来然后全部给gvw,gvw然后根据currentpageindex从中选取需要的数据,不要的数据放在内存中,这样的实现方式在数据量小的时候还好,在大数据量的时候是有很大的影响的。具体情况请点击这里

Administration文件夹中的AddProject.aspx页面实现了一种动态加载用户控件的技术。根据用户操作到第几步动态加载相应的用户控件进行显示,这些用户控件实现IEditProjectControl这个自定义接口 ...


Bugnet学习总结(5)逻辑层

Post on by michaelyin

Bugnet的逻辑层在在BugNET.BusinessLogicLayer这个namespace下,大多数类基本上是和数据库中的表相对应的,类里面一般就私有变量,方法,和属性,类中的方法调用DAL层的方法完成CRUD操作,没什么太复杂的地方。

把几个不一样的类稍微提一下,BugCollection是一个集合类,继承自CollectionBase,提供了排序的方法,里面包含的类实现了IComparer接口。

Globals这个类将公用的变量,数组,枚举放在了里面,方便编程的时候直接调用。

HostSettings是读取项目配置的类,从DAL读取后数据放在了Cache中,值得借鉴。

Mail是发送邮件的类,用xslt进行转换内容,然后调用.Net自带的函数进行邮件发送。


Bugnet学习总结(4)数据访问层

Post on by michaelyin

Bugnet由于功能比较简单,所以在系统的架构上也很简单,没什么过于复杂的地方。

DAL文件夹中的DataFactory文件通过读取Web.config中的Appsetting中的值反射生成生成数据库连接和操作对象。DataHelper,里面则是一些常用的Ado操作,进行了简单的封装,GenericDataAccessLayer是调用DataHelper里的函数完成数据CRUD操作的类。,需要提一下的是具体的数据库操作的代码是写在数据库的存储过程中的,而这一点也正是我不是很理解的地方,先前提到过的DataFactory和DataHelper特别是 DataFactory的存在是提供跨库操作的,而它将数据库操作又用存储过程写在数据库里面这不是有点矛盾么。。。想象一下如果要迁移的话那存储过程不是都还要改。。。。。:(

在看GenericDataAccessLayer的时候,刚开始我对其中一个语法结构不是很清楚,是到网上查了一些资料才弄懂的。该类在里面定义了一个静态对象,如果是别的对象我还可以理解,可是这个对象正式通过GenericDataAccessLayer实例化的。。

/// <summary>
/// BugNET Data Access Layer
/// </summary>
public class GenericDataAccessLayer
{
    private static GenericDataAccessLayer instance;
}

这个就是静态对象声明的地方

/// <summary>
/// Instances this instance.
/// </summary>
/// <returns></returns>
public static GenericDataAccessLayer Instance()
{
    if (instance == null)
    {
        instance = new GenericDataAccessLayer();
    }
    return instance;
}

在调用的时候如果为null会对对象进行初始化。

刚开始我的想法是GenericDataAccessLayer里包含instance这个对象,那初始化的时候会构成一个不断递归的过程,为什么会编译通过呢?后来在网上找了一下,找到了答案。原来类里面定义的静态对象是在类级别而不是在对象级别的。如果那种写法不是写的静态对象,即语句写成了public GenericDataAccessLayer Instance() ,那么肯定是有问题的,而如果你写在类这个级别的时候这个问题是不存在的。

这样来说吧 ...