The type of cast in the common method for another to call the common common method

I have 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 the 3rd party assembly:

  public class Record<T> where T : Record<T>, IRecordBase, new() { public static Record<T> FetchByID(object primaryKey) { /*...*/ } } 

My T and 3rd party T are not directly compatible, however, my objects that inherit from Record<T> also implement IDalRecord , so I can apply an instance of the object to any of these types.

But how can I pass the compiler "cast" (IDalRecord)T to (Record<T>)T ?

+4
source share
1 answer

It is not possible to tell the compiler that T inherits from Record<T> . The reason is simple: because it is not, generally speaking. In fact, your Get method could theoretically be called with any argument, not necessarily inherited from Record<T> .

The fact that T really inherits from Record<T> only becomes known at run time when your method is actually called. Therefore, the necessary checks and designs should take place at the same time.

 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 where clause var helper = Activator.CreateInstance( helperType ) as IHelper; return (T) helper.Fetch(primaryKey); } 

Keep in mind that it is completely (and even recommended) to cache those Helper<T> objects for performance.

You can also just use the old dumb reflection: find the FetchByID method by name and name it dynamically. But this can lead to a huge decrease in performance.

+5
source

All Articles