简体   繁体   English

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

[英]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. 我的T和第3方T不是直接兼容的,但是我从Record<T>继承的对象也实现了IDalRecord ,所以我可以将对象实例转换为这些类型中的任何一种。

But how can i tell the compiler to "cast" (IDalRecord)T to (Record<T>)T ? 但是我怎么能告诉编译器“转换” (IDalRecord)T(Record<T>)T

There is no way to tell the compiler that T actually inherits from Record<T> . 没有办法告诉编译器T实际上是从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> . 实际上,理论上,你的Get方法可以用任何参数调用,不一定是从Record<T>继承的。

The fact that T does, in fact, inherit from Record<T> only becomes known at runtime, when your method is actually called. 事实上, T实际上从Record<T>继承的事实只有在实际调用方法时才会在运行时知道。 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. 请记住,完全可能(甚至鼓励)缓存这些Helper<T>对象以提高性能。

You can also just use old dumb reflection: find the method FetchByID by name and call it dynamically. 您也可以使用旧的哑反射:按名称查找方法FetchByID并动态调用它。 But that would cause enormous performance penalty. 但这会导致巨大的性能损失。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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