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)
我找到了一个解决方法:
[<AbstractClass>]
type DummyProvider() =
inherit DataProviderBase<DummyProvider>()
let typeDef = typeof<DummyProvider>.BaseType.GetGenericTypeDefinition()
Run Code Online (Sandbox Code Playgroud)
有没有其他方法可以做到这一点,没有额外的类型?
我认为这实际上是一个非常好的问题。我没有找到更好的解决方法。您可以使用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<...>. 在这种情况下,默认机制根本不起作用......