Кажется, вы хотите выполнить какую-то операцию над множеством (пересечение? Исключение?) Над скалярными значениями. Вы можете решить эту проблему с помощью обобщений (и DbDataReader.GetFieldValue<T>
) без необходимости использования отражения или Activator
, например, так:
Если вы намереваетесь вызывать эту функцию F
с сайтов вызова, где тип столбец colName
известен статически (т. е. во время компиляции), затем преобразуйте F
в общий метод c:
void F<T>( String colName, DbDataReader reader1, DbDataReader reader2 )
{
Itn32 rdr1Idx = reader1.GetOrdinal( colName );
Itn32 rdr2Idx = reader2.GetOrdinal( colName );
HashSet<T> hashSet = new HashSet<T>();
while( reader1.Read() && reader2.Read() )
{
T value1 = reader1.GetFieldValue<T>( rdr1Idx );
T value2 = reader2.GetFieldValue<T>( rdr2Idx );
hashSet.Add( value1 );
hashSet.Add( value2 );
// etc - whatever logic you want here.
}
}
Используется примерно так:
F<Int32>( "someIntegerColumn", rdr1, rdr2 );
F<float>( "someNumericColumn", rdr1, rdr2 );
// etc
Если используемый тип может быть известен только во время выполнения (например, из-за предоставленных пользователем SQL запросов), тогда мы должны будем использовать Activator
, но все еще можем использовать HashSet<>
косвенно, оборачивая его в адаптер:
using System.Collections;
void F( String colName, DbDataReader reader1, DbDataReader reader2 )
{
Itn32 rdr1Idx = reader1.GetOrdinal( colName );
Itn32 rdr2Idx = reader2.GetOrdinal( colName );
Type columnType1 = reader1.GetFieldType( rdr1Idx );
Type columnType2 = reader2.GetFieldType( rdr2Idx );
if( columnType1 != columnType2 ) throw new InvalidOperationException( "Columns have different types." );
var hashSet = (IList)Activator.CreateInstance( typeof(List<>).MakeGenericType( columnType1 ) );
while( reader1.Read() && reader2.Read() )
{
Object value1 = reader1.GetValue( rdr1Idx );
Object value2 = reader2.GetValue( rdr2Idx );
hashSet.Add( value1 ); // HashSetAdapter will cast `Object value1` to its internal `T` type.
hashSet.Add( value2 );
// etc - whatever logic you want here.
}
}
class HashSetAdapter<T> : IList<T> // TODO: Implement all of System.Collections.ICollection
{
private readonly HashSet<T> hs;
public HashSetAdapter()
{
this.hs = new HashSet<T>();
}
public void Add( Object value )
{
this.hs.Add( (T)value );
}
// TODO: Expose any other HashSet operations.
}