f# - 查找实现接口的类,使用反射,并在 F# 中实例化它们
问题描述
我正在努力实现以下目标:
我有一个名为IBotCommand的接口和一些实现它的类。我想通过反射找到所有这些类,实例化每个类的实例并将结果放入字典中。
界面如下:
type IBotCommands =
abstract member Name: unit -> string
abstract member Description: unit -> string
abstract member Help: unit -> string
abstract member Execute: MessageEventArgs -> string[] -> string
和代码:
let t = typeof<IBotCommands>
t.Assembly.GetTypes()
|> Seq.filter (fun x -> x.IsSubclassOf(t))
|> Seq.iter (fun x ->
(
let i = Activator.CreateInstance(x) :> IBotCommands
botCommands.[i.Name] <- i
)
)
我遇到的问题是 CreateInstance 行。CreateInstance 返回一个无法转换为 IBotCommands的obj类型。
我在 C# 中也有同样的功能,它可以正常工作,但 C# 版本正在使用动态:
public static IEnumerable<Type> FindClassSubclassOfType<T>()
{
var a = typeof(T)
.Assembly.GetTypes()
.Where(t => t.IsSubclassOf(typeof(T)))
.Select(t => t);
return a.ToList();
}
var types = ReflectionHelper.FindClassSubclassOfType<BotCommand>();
foreach (var t in types)
{
dynamic c = Activator.CreateInstance(t);
BotCommands[c.Name] = c;
}
我怎样才能让这种行为在 F# 中起作用?
您可以将对象强制转换为 F# 中的接口吗?这是我第一次在 F# 中使用接口
解决方案
a :> T
在 F# 中, upcast 和 downacst是有区别的a :?> T
。
当编译器静态知道
a
实现了一个接口时,使用 UpcastT
。如果您有一个具体类的值并且想要获得一个具有接口类型的值,这将很有用。当编译器不能静态知道是否
a
实现了接口时,使用向下转换。换句话说,这意味着强制转换可能会失败。
在您的情况下,您需要向下转换,因为编译器不知道是否obj
实现了IBotInterface
. 您需要做的就是添加?
:
let i = Activator.CreateInstance(x) :?> IBotCommands
botCommands.[i.Name] <- i
推荐阅读
- codeigniter - uri-encode-permitted chars 不起作用
- android - DexOverflowException:无法在 main-dex 文件中容纳请求的类
- c# - Nsubstitute - 当处理程序使用泛型时引发模拟对象的事件
- msbuild - VSTS 如何使用多项目解决方案创建包文件(zip)
- android - 在 Oreo 中自定义 google setupwizard 时出现安全异常
- sql-server - 使用在 MSSQL 中使用 EncryptByPassPhrase() 加密的 powershell 解密字符串
- r - 我正在 Rstudio 中进行参数化降价,并且无法更改使用 ggplot2 生成的条形图的颜色
- angular - 如何在 Angular 中的验证指令中触发 ngOnChanges 上的验证函数?
- dronekit-python - 在 2 个 python 代码上调用 vehicle = connect() 导致连接断开
- mapbox-gl-js - Mapbox 属性函数:基值