将泛型方法中的类型转换为内部泛型方法调用的不同方法

Mux*_*uxa 4 .net c# generics casting

我有这个存储库方法:

    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
    }
Run Code Online (Sandbox Code Playgroud)

在第三方聚会中定义:

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

T和第三方T不是直接兼容的,但是我继承的对象Record<T>也实现了IDalRecord,所以我可以将对象实例转换为这些类型中的任何一种.

但是,我怎么能告诉编译器"投" (IDalRecord)T(Record<T>)T

Fyo*_*kin 5

没有办法告诉编译器T实际上继承自Record<T>.原因很简单:一般来说,这不是真的.实际上,从Get理论上讲,你的方法可以用任何参数调用,不一定是继承自的Record<T>.

事实上,只有在实际调用方法时才会在运行时知道T这一事实Record<T>.因此,必须在同一时刻进行必要的检查和构造.

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);
}
Run Code Online (Sandbox Code Playgroud)

请记住,完全可能(甚至鼓励)缓存这些Helper<T>对象以提高性能.

您也可以使用旧的哑反射:按名称查找方法FetchByID并动态调用它.但这会导致巨大的性能损失.