【发布时间】:2013-03-27 18:48:40
【问题描述】:
这个问题的扩展passing static reflection information to static generic methods
我正在尝试创建一个通用类型读取器,因为我使用类进行大量数据访问,并且我正在尝试创建一个相当通用的方法,允许在没有太多代码的情况下读取数据。
完成大部分阅读的代码部分看起来像这样
public static T Read<T>(string field,IDataRecord data )
{
Type type1 = typeof (T);
try
{
if (type1 == typeof( String ))
{
return (T)Convert.ChangeType( readString( data[field].ToString() ), typeof( T ) );
}
if (type1 == typeof( int? ))
{
return (T)Convert.ChangeType( readIntN( data[field].ToString() ), typeof( T ) );
}
if (type1 == typeof( Guid? ))
{
return (T)Convert.ChangeType( readGuidN( data[field].ToString() ), typeof( T ) );
}
if (type1 == typeof( double? ))
{
return (T)Convert.ChangeType( readDoubleN( data[field].ToString() ), typeof( T ) );
}
if (type1 == typeof( decimal? ))
{
var res = readDecimalN(data[field].ToString());
return (T)Convert.ChangeType( res, typeof( T ) );
}
if (type1 == typeof( float? ))
{
return (T)Convert.ChangeType( readFloatN( data[field].ToString() ), typeof( T ) );
}
if (type1 == typeof( bool? ))
{
return (T)Convert.ChangeType( readBoolN( data[field].ToString() ), typeof( T ) );
}
if (type1 == typeof( DateTime? ))
{
return (T)Convert.ChangeType( readDatetimeN( data[field].ToString() ), typeof( T ) );
}
if (type1 == typeof( int ))
{
return (T)Convert.ChangeType( readInt( data[field].ToString() ), typeof( T ) );
}
if (type1 == typeof( long? ))
{
return (T)Convert.ChangeType( readLongN( data[field].ToString() ), typeof( T ) );
}
if (type1 == typeof( long ))
{
return (T)Convert.ChangeType( readLong( data[field].ToString() ), typeof( T ) );
}
if (type1 == typeof( Guid ))
{
return (T)Convert.ChangeType(readGuid( data[field].ToString() ), typeof( T ) );
}
if (type1 == typeof( double ))
{
return (T)Convert.ChangeType( readDouble( data[field].ToString() ), typeof( T ) );
}
if (type1 == typeof( decimal ))
{
return (T)Convert.ChangeType( readDecimal( data[field].ToString() ), typeof( T ) );
}
if (type1 == typeof( float ) || type1 == typeof( Single ))
{
return (T)Convert.ChangeType( readFloat( data[field].ToString() ), typeof( T ) );
}
if (type1 == typeof( bool ))
{
return (T)Convert.ChangeType( readBool( data[field].ToString() ), typeof( T ) );
}
if (type1 == typeof( DateTime ))
{
return (T)Convert.ChangeType( readDatetime( data[field].ToString() ), typeof( T ) );
}
}
catch (Exception)
{
throw;
}
throw new Exception(String.Format("Data Type Not Supported: {0}", type1));
}
但是,这会引发 Invalid Cast Exception。
readXXX 方法运行良好,但每个返回语句都出现问题
我也尝试过使用
public static T SafeConvert<T>(string s, T defaultValue)
{
if ( string.IsNullOrEmpty(s) )
return defaultValue;
return (T)Convert.ChangeType(s, typeof(T));
}
但还是失败了
编辑:
方法正在通过
调用private static List<T> GetItems<T>(IDataReader reader)
{
var items = new List<T>();
while (reader.Read())
{
Type type1 = typeof (T);
var item = (T) Activator.CreateInstance(typeof (T), new object[] {});
foreach (PropertyInfo info in type1.GetProperties())
{
int written = 0;
if (info.CanWrite)
{
#region
try
{
Type dataType = info.PropertyType;
MethodInfo method = typeof (DataReader).GetMethod("Read",BindingFlags.Static | BindingFlags.Public);
MethodInfo generic = method.MakeGenericMethod(dataType);
var t = generic.Invoke(null, new object[] {info.Name, reader});
info.SetValue( item, t );
更多...
人们似乎在问我用它做什么,最终它允许我在一行中创建一个 ienumerable,它可以通过传递文件位置或 sql 查询从任何来源读取,无论是 CSV 还是 SQL,即
//returns Ienumerable<MyClass>
var list = Reader.ReadSql<MyClass>(DataBases.Test,"select * from TestTable where someAttribute = 1");
// also returns Ienumerable MyClass
var list2 = Readre.ReadCsv<MyClass>(@"c:\file1.csv",",");
我现在运行它,但它需要在每个实现中重复 if dataType == typeof(string) 的长列表我希望将其重构为单个通用读取方法,但在转换时遇到问题
【问题讨论】:
-
您已经发布了 很多 代码,但没有显示您是如何调用该方法或值是什么。这很难帮助你。此外,您的 try/catch 块毫无意义 - 您只是重新抛出原始异常。
-
您没有说,但我猜对于不实现 IConvertable 的类型(例如 Guid)会引发异常。您必须为这些类型调用构造函数。
-
嗨,乔恩,调用是在上一个问题中进行的,如顶部链接,我将在这个问题中添加更多细节(是的,我知道 try catch 是不必要的,目前使用它进行调试)
-
嗯...看起来您可能正在尝试制作 DataTable 的“类型安全”版本...准确吗?
-
@Yakyb,如果我没看错,您是在尝试手动实现序列化吗?为什么不使用内置的 C# 序列化方法/接口?
标签: c# generics reflection