如何使用泛型将DataReader对象映射到类对象?
例如,我需要执行以下操作:
public class Mapper<T>
{
public static List<T> MapObject(IDataReader dr)
{
List<T> objects = new List<T>();
while (dr.Read())
{
//Mapping goes here...
}
return objects;
}
}
后来我需要调用这个类方法,如下所示:
IDataReder dataReader = DBUtil.Fetchdata("SELECT * FROM Book");
List<Book> bookList = Mapper<Book>.MapObject(dataReder);
foreach (Book b in bookList)
{
Console.WriteLine(b.ID + ", " + b.BookName);
}
请注意,Mapper类应该能够映射由T.表示的任何类型的对象。
答案 0 :(得分:3)
我将ValueInjecter用于此
我这样做:
while (dr.Read())
{
var o = new User();
o.InjectFrom<DataReaderInjection>(dr);
yield return o;
}
你需要这个ValueInjection来实现这个目的:
public class DataReaderInjection : KnownSourceValueInjection<IDataReader>
{
protected override void Inject(IDataReader source, object target, PropertyDescriptorCollection targetProps)
{
for (var i = 0; i < source.FieldCount; i++)
{
var activeTarget = targetProps.GetByName(source.GetName(i), true);
if (activeTarget == null) continue;
var value = source.GetValue(i);
if (value == DBNull.Value) continue;
activeTarget.SetValue(target, value);
}
}
}
答案 1 :(得分:2)
好吧,我不知道它是否适合这里,但你可以使用yield关键字
public static IEnumerable<T> MapObject(IDataReader dr, Func<IDataReader, T> convertFunction)
{
while (dr.Read())
{
yield return convertFunction(dr);
}
}
答案 2 :(得分:1)
您可以使用我写的这个LateBinder类:http://codecube.net/2008/12/new-latebinder/。
我写了另一篇文章,用法为:http://codecube.net/2008/12/using-the-latebinder/
答案 3 :(得分:1)
由于你基本上试图将两个未知数映射在一起,这将很难做到。在您的通用对象中,类型是未知的,而在您的datareader中,该表是未知的。
所以我建议你创建一些列属性来附加到你实体的属性。然后查看这些属性属性,并尝试从datareader中的这些属性中查找数据。
你最大的问题是,如果在阅读器中找不到其中一个属性会发生什么,反之亦然,在实体中找不到阅读器中的一列。
祝你好运,但是如果你想做这样的事情,你可能想要一个ORM,或者至少需要一些Active Record实现。答案 4 :(得分:1)
我能想到的最简单的方法是提供一个Func<T,T>
代表来转换每一栏并构建你的书。
或者,如果你遵循一些约定,你可以通过反射来处理这个问题。例如,如果每个列使用相同的名称映射到结果对象中的属性,并且您在Mapper中限制T以提供可构造的T,则可以使用反射将每个属性的值设置为相应列中的值
答案 5 :(得分:1)
我认为你不能以某种形式定义字段之间的关系。看看这篇文章,特别注意如何定义映射,它可能适合你。
http://www.c-sharpcorner.com/UploadFile/rmcochran/elegant_dal05212006130957PM/elegant_dal.aspx
答案 6 :(得分:1)
如何关注
abstract class DataMapper
{
abstract public object Map(IDataReader);
}
class BookMapper : DataMapper
{
override public object Map(IDataReader reader)
{
///some mapping stuff
return book;
}
}
public class Mapper<T>
{
public static List<T> MapObject(IDataReader dr)
{
List<T> objects = new List<T>();
DataMapper myMapper = getMapperFor(T);
while (dr.Read())
{
objects.Add((T)myMapper(dr));
}
return objects;
}
private DataMapper getMapperFor(T myType)
{
//switch case or if or whatever
...
if(T is Book) return bookMapper;
}
}
不知道它是否在语法上是正确的,但我希望你明白这一点。
答案 7 :(得分:1)
如何使用 Fluent Ado.net ?
答案 8 :(得分:1)
答案 9 :(得分:1)
我建议您使用AutoMapper。