Reputation: 5643
I've got this repository method:
public virtual T Get<T>(object primaryKey) where T : IDalRecord, new() //note: can't change the where clause
{
return Record<T>.FetchByID(primaryKey); // how? <--compile time error
}
defined in a 3-rd party assembly:
public class Record<T> where T : Record<T>, IRecordBase, new()
{
public static Record<T> FetchByID(object primaryKey) { /*...*/ }
}
My T
and the 3-rd party T
are not directly compatible, however my objects that inherit from Record<T>
also also implement IDalRecord
, so i can cast the object instance to any of these type.
But how can i tell the compiler to "cast" (IDalRecord)T
to (Record<T>)T
?
Upvotes: 4
Views: 197
Reputation: 80754
There is no way to tell the compiler that T
actually inherits from Record<T>
. The reason is simple: because it is not true, generally speaking. Indeed, your Get
method may, theoretically, be called with any argument, not necessarily that inheriting from Record<T>
.
The fact that T
does, in fact, inherit from Record<T>
only becomes known at runtime, when your method is actually called. Therefore, necessary checks and constructs must take place at that same moment.
interface IHelper { object Fetch(object key); }
class Helper<T> : IHelper where T : Record<T>, IRecordBase, new()
{
public object Fetch(object key) { return Record<T>.FetchByID(key); }
}
public virtual T Get<T>(object primaryKey) where T : IDalRecord, new()
{
var helperType = typeof( Helper<> ).MakeGenericType( typeof( T ) );
// This will throw an exception if T does not satisfy Helper's where clause
var helper = Activator.CreateInstance( helperType ) as IHelper;
return (T) helper.Fetch(primaryKey);
}
Keep in mind that is it entirely possible (and even encouraged) to cache those Helper<T>
objects for performance.
You can also just use old dumb reflection: find the method FetchByID by name and call it dynamically. But that would cause enormous performance penalty.
Upvotes: 5