[英]Find all specific types, with reflection, in assemblies loaded by the application with .net core
Note: although the example code is in F#, I'm not specifically looking for a F# answer but for the .net calls I need to do, so an answer in C# or F# is fine.注意:虽然示例代码在 F# 中,但我并不是专门寻找 F# 的答案,而是我需要做的 .net 调用,所以 C# 或 F# 中的答案是可以的。
I have a system where there are commands, for a chat bot, scattered in different part of the code.我有一个系统,其中有命令,用于聊天机器人,分散在代码的不同部分。 I find, and register, them all through reflection using this code:我使用这段代码通过反射找到并注册了它们:
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)
)
)
It's in F#, but I think the method calls give away what it does if you're more familiar with C#.它在 F# 中,但我认为如果您更熟悉 C#,方法调用就会泄露它的作用。
So, I do Assembly.GetTypes, keep the ones where GetInterface has the interface name I'm looking for and then I instantiate them.因此,我执行 Assembly.GetTypes,保留 GetInterface 具有我正在寻找的接口名称的那些,然后实例化它们。
This works well, but only within its own assembly.这很好用,但只在它自己的程序集中。 My question is how can I expand this to all assemblies loaded by the app (but the system ones to not waste time)?我的问题是如何将其扩展到应用程序加载的所有程序集(但系统程序集不会浪费时间)?
You can use Assembly.GetReferencedAssemblies
on t.Assembly
, filter out System
references by their name and then Assembly.Load
on the names to load a sequence of assemblies.您可以在t.Assembly
上使用Assembly.GetReferencedAssemblies
,按名称过滤掉System
引用,然后在名称上使用Assembly.Load
以加载一系列程序集。 From there you can do a Seq.collect
on Assembly.GetTypes()
.从那里您可以在Assembly.GetTypes()
上执行Seq.collect
。
Have your user assemblies define an assembly level attribute - which you can check for, to decide further scan the library.让您的用户程序集定义程序集级别的属性 - 您可以检查该属性,以决定进一步扫描库。 This is more robust than figuring out which assemblies to black-list, for eg, you may not want to scan Newtonsoft.Json
.这比确定将哪些程序集列入黑名单更可靠,例如,您可能不想扫描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")
If your requirements are going to be more complex in the future, it might be worth taking a look at MEF.如果您的要求将来会变得更加复杂,那么 MEF 可能值得一看。
let catalog = new DirectoryCatalog("./")
let container = new CompositionContainer(catalog)
container.ComposeParts()
let instances = container.GetExports<IBotCommands, IBotCommandMetadata>()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.