Dotnet 工具箱DotNetCorePlugins- 动态加载和卸载 .NET 程序插件

Posted dotnet-box

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Dotnet 工具箱DotNetCorePlugins- 动态加载和卸载 .NET 程序插件相关的知识,希望对你有一定的参考价值。

你好,这里是 Dotnet 工具箱,定期分享 Dotnet 有趣,实用的工具和组件,希望对您有用!

1. DotNetCorePlugins- 动态加载和卸载 .NET 程序插件

DotNetCorePlugins 是一个 .NET 的开源插件项目,它提供了能够动态加载程序集的 API,然后把它们作为 .NET 主程序的扩展程序执行。

这个库主要用到了 AssemblyLoadContext 技术, System.Runtime.Loader.AssemblyLoadContext,又名 ALC,提供了一些用于定义动态程序集加载行为的基本 API。这是 .NET Core 中我最喜欢但鲜为人知的 API 之一。

如何使用?

安装 McMaster.NETCore.Plugins NuGet 包。

dotnet add package McMaster.NETCore.Plugins

主要使用的 API 是 PluginLoader.CreateFromAssemblyFile, 它允许从文件中读取并加载程序集。

PluginLoader.CreateFromAssemblyFile(
    assemblyFile: "./plugins/MyPlugin/MyPlugin1.dll",
    sharedTypes: new []  typeof(IPlugin), typeof(IServiceCollection), typeof(ILogger) ,
    isUnloadable: true)
  • assemblyFile = 插件 .dll 的文件路径
  • sharedTypes = 加载程序的统一的类型列表
  • isUnloadable = 允许这个插件在将来的某个时候从内存中卸载。

定义接口

这是一个示例,我们定义了一个接口,里面包含了 GetName, 如下

public interface IPlugin

    string GetName();

对于插件,我们直接使用这个接口并进行实现,如下

internal class MyPlugin1 : IPlugin

    public string GetName() => "My plugin v1";

对于主程序,我们可以使用 PluginLoader API 来加载插件,程序需要使用查找磁盘中的插件程序集。一种方式是基于约定的,比如

plugins/
    $PluginName1/
        $PluginName1.dll
        (additional plugin files)
    $PluginName2/
        $PluginName2.dll

每个插件都发布到一个单独的目录中,这样可以避免插件之间的争用和重复的依赖问题。

以通过运行下面的命令,输出插件到文件夹中。

dotnet publish MyPlugin1.csproj --output plugins/MyPlugin1/

接下来,我们可以通过反射获取所有的插件,并进行加载, 代码如下

using McMaster.NETCore.Plugins;

var loaders = new List<PluginLoader>();

// create plugin loaders
var pluginsDir = Path.Combine(AppContext.BaseDirectory, "plugins");
foreach (var dir in Directory.GetDirectories(pluginsDir))

    var dirName = Path.GetFileName(dir);
    var pluginDll = Path.Combine(dir, dirName + ".dll");
    if (File.Exists(pluginDll))
    
        var loader = PluginLoader.CreateFromAssemblyFile(
            pluginDll,
            sharedTypes: new []  typeof(IPlugin) );
        loaders.Add(loader);
    


// Create an instance of plugin types
foreach (var loader in loaders)

    foreach (var pluginType in loader
        .LoadDefaultAssembly()
        .GetTypes()
        .Where(t => typeof(IPlugin).IsAssignableFrom(t) && !t.IsAbstract))
     
        IPlugin plugin = (IPlugin)Activator.CreateInstance(pluginType);

        Console.WriteLine($"Created plugin instance \'plugin.GetName()\'.");
    

支持 MVC 和 Razor

另外插件还支持加载 MVC 的 Controller 和 Razor Pages。通过安装下面的 Nuget 包。

dotnet add package McMaster.NETCore.Plugins.Mvc

加载程序集的方法如下:

public class Startup

    public void ConfigureServices(IServiceCollection services)
    
        var pluginFile = Path.Combine(AppContext.BaseDirectory, "plugins/MyRazorPlugin/MyRazorPlugin.dll");
        services
            .AddMvc() 
            .AddPluginFromAssemblyFile(pluginFile);
    

更多插件的使用方法,作者提供了一些示例项目,可以进行参考。

https://github.com/natemcmaster/DotNetCorePlugins

2. 推荐一个强大高效的开源 .NET 访问控制组件

Casbin 简介

Casbin 是一个强大高效的开源访问控制库,支持各种 访问控制模型 , 如 ACL, RBAC, ABAC 等。

我们希望可以让指定的主体 subject,可以访问指定的资源 object,访问可以是读和写。这就是 Casbin 使用最广泛的方式。也称为 subject, object, action 流程。

另外,Casbin 能够处理标准流程以外的许多复杂授权场景,还支持添加 RBAC 和 ABAC 等。

Casbin 能做什么?

  1. subject, object, action 定义访问策略,支持允许和拒绝授权。
  2. 处理访问控制模型和策略的存储。
  3. 管理角色-用户映射和角色-角色映射(也称为 RBAC 中的角色层次结构)。
  4. 支持内置超级用户,例如rootadministrator。超级用户可以在没有明确许可的情况下做任何事情。
  5. 内置多种运算符,支持规则匹配。例如,keyMatch可以将资源键映射/foo/bar到模式/foo*

Casbin 不做的事

  1. 用户身份验证。
  2. 管理用户和角色列表。

Casbin 支持的语言

Casbin 提供对各种编程语言的支持,可以集成到任何项目和工作流程中:

它是怎么运行的?

在Casbin中,基于PERM元模型 (Policy, Effect, Request, Matchers)将一个访问控制模型抽象成一个CONF文件。

所以切换或升级项目的授权机制就像修改配置一样简单。

Casbin中 最基本最简单的模型就是ACL。ACL 的模型 CONF 是:

# Request definition
[request_definition]
r = sub, obj, act

# Policy definition
[policy_definition]
p = sub, obj, act

# Policy effect
[policy_effect]
e = some(where (p.eft == allow))

# Matchers
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act

ACL 模型的示例策略如下:

p, alice, data1, read
p, bob, data2, write

它的意思是:

  • alice 可以读取 data1.
  • bob 可以写入 data2。

如何使用?

首先,需要安装 Casbin.NET。

dotnet add package Casbin.NET
  1. 使用模型文件和策略文件新建一个 Casbin 执行器:
   var e = new Enforcer("path/to/model.conf", "path/to/policy.csv")

注意:这里您还可以使用数据库中的策略而不是文件来初始化执行器。

  1. 在进行资源访问的时候,使用下面的授权代码。
var sub = "alice";  # 想要访问资源的用户
var obj = "data1";  # 将要被访问的资源
var act = "read";  # 用户对资源进行的操作

if (await e.EnforceAsync(sub, obj, act)) 

    // 允许alice读取data1

else

    // 拒绝请求,抛出异常

https://github.com/casbin/Casbin.NET

微软的dotnet-new工具可以使创建JavaScript Web 程序变得更简单

Microsoft发布了一组工具,使用他们的dotnet-new工具和使用Node.js的灵活方法可以快速生成基于JavaScript的Web 应用程序。

dotnet-new工具是.NET Core工具的一部分,用于使用简单的命令启动一个新项目。作为ASP.NET Core JavaScript Services的一部分,Web开发人员现在可以使用相同的命令来启动新的单页应用程序(SPA)。

Steve Sanderson在一篇文章中写道,使用这些模板的目的是让初始更容易:“我们经常听说构建这些应用程序(使用Angular或React的SPA)很复杂。将服务器端和客户端代码集成到一起可能是一个挑战,甚至只是最初选择一个高效的项目计划。”

这些项目类型的可用性取决于Microsoft.AspNetCore.SpaTemplates NuGet包。一旦安装完成,使用这样的命令可以让angular、react、reactredux、aurelia和knockout启动:dotnet new reactredux

这些模板的源代码在GitHub中。由于这是一个.NET Core工具,安装这些模板之一会创建一个ASP.NET应用程序。“angular”是一个Angular 2+应用程序。

在JavaScript社区的其他地方,诸如create-react-app和Angular CLI等选项为大家熟知的Node.js和NPM提供了一种简单的方式来启动这些应用程序。基于dotnet-new的.NET为开发人员提供了他们可能更熟悉Microsoft环境选项。但是,在某些方面,这些新的.NET工具会更全面。

例如,angular和reactredux模板包括了默认的服务器端呈现(它可以被关闭)。所有这些项目类型都使用Webpack 2来捆绑前端代码(除了aurelia模板),默认情况下已启用Hot Module Replacement。

虽然这是一个.NET应用程序,但它仍然通过SpaServices来使用Node.js。SpaServices使用Microsoft.AspNetCore.NodeServices来让ASP.NET开发人员使用Node.js系统,而不直接实际运行Node.js。Sanderson说,这一切都发生在“幕后”:例如,要在服务器上预生成Angular或React组件,它需要在服务器上执行JavaScript。它通过NodeServices来实现,它启动隐藏的Node.js实例并提供一种可以快速稳健的从.NET中进行调用方法。

Sanderson也是knockout.js的创造者。

Microsoft Office 365 商业版下载>>>>

【文章来源慧都控件,原创不易,转载请注明出处】


以上是关于Dotnet 工具箱DotNetCorePlugins- 动态加载和卸载 .NET 程序插件的主要内容,如果未能解决你的问题,请参考以下文章

无法启动 dotnet 核心进程。添加工具失败

.NET GC 实时监控工具 dotnet gcmon 介绍

用于在编译时删除未使用的命令行工具或 dotnet 工具

[Cake] 2. dotnet 全局工具 cake

微软的dotnet-new工具可以使创建JavaScript Web 程序变得更简单

dotnet-exec 小工具