It seems you're wanting to perform some kind of Set Operation (Intersection? Exclusion?) over scalar values. You can solve this problem using generics (and DbDataReader.GetFieldValue<T>
) without needing to use reflection or Activator
, like so:
If you intend to call this F
function from call-sites where the type of the colName
column is known statically (i.e. at compile time), then convert F
to a generic method:
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.
}
}
Used like so:
F<Int32>( "someIntegerColumn", rdr1, rdr2 );
F<float>( "someNumericColumn", rdr1, rdr2 );
// etc
If the Type being used can only be known at runtime (e.g. because of user-supplied SQL queries) then we'll have to use Activator
, but can still use a HashSet<>
indirectly by wrapping it in an adapter:
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.
}