c# 泛型+反射

本文介绍了一个用于账套间数据复制的功能实现方法,通过泛型接口和反射技术来减少代码重复,并实现了灵活的数据操作。具体实现包括条件删除、数据复制及更新等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

程序的账套模块,有一个账套间相互复制数据的功能,有几个表需要实现这个功能。这些表有共有属性: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

转载于:https://www.cnblogs.com/icyJ/archive/2013/05/03/generic_interface.html

C# 中,这三个概念——、特性(Attribute)和反射(Reflection)都是为了提升代码的可复用性和灵活性。 **(Generics)**: - 是一种编程技术,它允许你在编写代码时指定类参数,从而使代码能够适用于多种数据类,而无需为每种类单独编写代码。 - 有助于减少复制和粘贴(DRY原则),提高代码的通用性和性能(编译期类检查)。 - 示例:```csharp public class List<T> { ... } // T 代表任何数据类 var myList = new List<int>(); // 使用了,T 替换为 int 类 ``` **特性(Attribute)**: - 特性是一种元数据形式,用于附加额外信息到编译单元、类、字段、属性、方法等上。 - 开发者可以自定义特性并编写处理程序来访问这些附加信息,例如标记法注解、验证规则等。 - 示例:```csharp [AgeRange(18, 60)] // 自定义 AgeRange 属性 public class Person { ... } public class AgeRangeAttribute : Attribute { public int Min { get; set; } public int Max { get; set; } } ``` **反射(Reflection)**: - 反射是运行时获取和修改程序结构的能力,包括获取类信息、字段、方法、构造函数等,并在运行时动态调用。 - 这在需要在运行时动态解析代码、插件化开发或者生成代码等方面非常有用。 - 示例:```csharp Type personType = typeof(Person); // 获取 Person 类的信息 FieldInfo ageField = personType.GetField("Age"); // 获取年龄字段 ageField.SetValue(personInstance, 30); // 动态设置年龄值 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值