c# 泛型+反射

程序的账套模块,有一个账套间相互复制数据的功能,有几个表需要实现这个功能。这些表有共有属性:User_ID和Count_Set_ID。为了节省代码,我用一个接口规范了这几个类,其中接口包含上面两个属性。

数据的操作是在Linq To Sql的基础上实现的。所以操作大对象是DataClasses1DataContext db,自对象是db.Table.

具体的操作是,针对表一,有两个key,UserID+CountSetID。首先需要查询旧CountSetID下的所有数据,然后修改其CountSetID为目标ID,最后全部插入到数据库,完成。

扩展功能:在复制数据之前,可能要先删除目标ID下的所有数据。

void CopyCountSetSub<T>(System.Data.Linq.Table<T> data, int sourceID, int targetID, bool deleteB4Copy)
    where T : class, ICountSet
{
    if (deleteB4Copy)//删除旧数据
    {
        var oldData = data.Where(x => x.User_ID == UserID && x.Count_Set_ID == targetID);
        data.DeleteAllOnSubmit(oldData);
    }
    var targetData = data.Where(x => x.User_ID == UserID && x.Count_Set_ID == sourceID).ToList();
    targetData.ForEach(x =>
    {
        T newX = (T)System.Activator.CreateInstance(typeof(T), x);//利用反射取得带参数的构造函数
        newX.Count_Set_ID = targetID;
        data.InsertOnSubmit(newX);
    });
}

上面的方法的参数:System.Data.Linq.Table<T> data将整个数据库映射对象传递过来。nt sourceID是源账套ID,int targetID是目标账套ID,bool deleteB4Copy则表示是否在复制前删除。

where T : class, ICountSet。约束此泛型方法的类型。其必须是类,必须继承自接口ICountSet。继承接口的作用是为了在方法中调用x.User_ID和x.Count_Set_ID。

方法的内容逻辑很明确:首先判断执行删除,然后赋值旧数据,在旧数据的基础上生成新数据,然后插入数据库。

这里有一个扩展,泛型类型的带一个参数的构造函数。本来泛型约束中有new(),如果where 后面约束了new(),可以这么做:   T newOne = new T();使用前提是T必须有无参数的构造函数。而在这里,我们需要 T newOne = new T(x);没有new(T)的约束,直接这么敲代码,肯定得错,在这个泛型方法里面,不能判断T是否有这么一个构造函数。最后值得用反射来获得T的带参数的构造函数T newX = (T)System.Activator.CreateInstance(typeof(T), x); 传入x作为参数,创建一个实例并强制转换成类型T。随后修改newX的Count_Set_ID的值,然后插入数据库即即刻。

本片重点:泛型的使用;泛型的约束where,包括new(),class,Iinterface等;反射获取类型的带参数的构造函数并创建实例。

转载请注明出处:http://www.cnblogs.com/icyJ

posted @ 2013-05-03 15:17  脸谱匠  阅读(1018)  评论(0编辑  收藏  举报