c# - 使用 .net 核心在应用程序加载的程序集中查找所有特定类型,并使用反射
问题描述
注意:虽然示例代码使用 F#,但我并不是专门寻找 F# 答案,而是寻找我需要做的 .net 调用,因此 C# 或 F# 中的答案很好。
我有一个系统,其中有用于聊天机器人的命令,分散在代码的不同部分。我使用以下代码通过反射找到并注册它们:
member private this.RegisterCommands() =
let t = typeof<IBotCommands>
t.Assembly.GetTypes()
|> Seq.filter (fun x -> x.GetInterface(t.Name) <> null)
|> Seq.iter (fun x ->
(
let i = (Activator.CreateInstance(x)) :?> IBotCommands
botCommands.[i.Name()] <- i
i.Initialize(this)
)
)
它在 F# 中,但如果您更熟悉 C#,我认为方法调用会放弃它的作用。
所以,我做 Assembly.GetTypes,保留 GetInterface 具有我正在寻找的接口名称的那些,然后我实例化它们。
这很好用,但只能在它自己的程序集中。我的问题是如何将其扩展到应用程序加载的所有程序集(但系统程序集不会浪费时间)?
解决方案
让您的用户程序集定义一个程序集级别属性 - 您可以检查它,以决定进一步扫描库。这比找出将哪些程序集列入黑名单更可靠,例如,您可能不想扫描Newtonsoft.Json
.
Assembly
.GetEntryAssembly()
.GetReferencedAssemblies()
|> Seq.map (fun assm -> Assembly.Load assm.FullName)
|> Seq.append (Seq.singleton (Assembly.GetEntryAssembly()))
|> Seq.filter (fun assm -> assm.IsDefined(useAttrib) )
|> Seq.collect(fun assm -> assm.GetTypes())
|> Seq.filter (fun x -> interfaceType.IsAssignableFrom(x))
|> Seq.iter (printfn "%A")
如果您的要求将来会变得更加复杂,那么可能值得一看 MEF。
let catalog = new DirectoryCatalog("./")
let container = new CompositionContainer(catalog)
container.ComposeParts()
let instances = container.GetExports<IBotCommands, IBotCommandMetadata>()
推荐阅读
- python - 如何检查matplotlib中的子图是否为空
- c++ - Xcode Sanitizer 如何启用
- rust - E0308 在过滤器中使用闭包时类型不匹配(“一种类型比另一种更通用”)
- sql - Oracle SQL - 我可以在 DDL 的 CHECK 约束中使用子查询吗?
- clang-format - 即使有注释,如何在同一行强制使用括号
- javascript - 如何检测 Angular 中选择了 mat-autocomplete 选项?
- go - 扩展或解包结构作为测试的输入参数
- html - Gatsby 将 lang 属性设置为 html
- ruby-on-rails - 如何使用 Resque 和 Redis 对队列进行优先级排序
- reactjs - 获取 TS 错误:“IAuth | 类型”上不存在属性“用户” 无效的'