简体   繁体   中英

Cast type in a generic method to a different one for inner generic method call

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 ?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM