如何获取CRTP类型的泛型类型定义

Dan*_*iel 5 reflection f# crtp

在C#中给出以下CRTP类型:

public abstract class DataProviderBase<TProvider>
    where TProvider : DataProviderBase<TProvider> { }
Run Code Online (Sandbox Code Playgroud)

我如何在F#中获得其泛型类型定义?

let typeDef = typedefof<DataProviderBase<_>>
Run Code Online (Sandbox Code Playgroud)

产生错误:

对类型推断变量应用默认类型"DataProviderBase <'a>"时,键入约束不匹配.统一''a'和'DataProviderBase <'时,结果类型将是无限的'a>考虑添加更多类型约束

在C#中,它将是:

var typeDef = typeof(DataProviderBase<>);
Run Code Online (Sandbox Code Playgroud)

UPDATE

我找到了一个解决方法:

[<AbstractClass>]
type DummyProvider() =
  inherit DataProviderBase<DummyProvider>()

let typeDef = typeof<DummyProvider>.BaseType.GetGenericTypeDefinition()
Run Code Online (Sandbox Code Playgroud)

有没有其他方法可以做到这一点,没有额外的类型?

Tom*_*cek 5

我认为这实际上是一个非常好的问题。我没有找到更好的解决方法。您可以使用typedefof以下方法稍微简化您的解决方法:

let typeDef = typedefof<DataProviderBase<DummyProvider>>
Run Code Online (Sandbox Code Playgroud)

技术细节

问题在于 F#typedefof<'T>只是一个带有类型参数的普通函数(与typeofC# 中的运算符不同)。为了调用它,您需要给它一个实际类型,然后该函数将GetGenericTypeDefinition在掩护下调用。

有效的原因typedefof<option<_>>是 F# 将默认类型指定为参数(在本例中为obj)。通常,F# 选择与约束匹配的不太具体的类型。在你的情况下:

DataProviderBase<_> 将成为 DataProviderBase<DataProviderBase<_>>等等。

除非您定义新类型(如在您的解决方法中),否则没有具体类型可以用作typedefof<...>. 在这种情况下,默认机制根本不起作用......