简体   繁体   English

C#:对插件使用“类库”项目

[英]C#: use “Class Library” Project for plugins

this question follows my previous question . 这个问题遵循我之前的问题 I have ac# ASP.NET application and i want to provide support for plugins. 我有ac#ASP.NET应用程序,我想为插件提供支持。 Plugins can be custom c# classes, javascript, html, css, images, etc. 插件可以是自定义c#类,javascript,html,css,图像等。

I see no problem as long as my application is extended with c# classes because all the user has to do is create a new "class library" project in visual studio and implement the interfaces, i provide. 只要我的应用程序使用c#类扩展,我就没有问题,因为所有用户必须做的是在visual studio中创建一个新的“类库”项目并实现我提供的接口。 Then build a dll out of it and upload it to my server. 然后从中构建一个DLL并将其上传到我的服务器。 The plugin-developer can add static files (html, js, css, etc.) into this project as well but i found some problems with that: 插件开发人员也可以将静态文件(html,js,css等)添加到这个项目中,但我发现了一些问题:

  1. Every static file i add to the plugin project gets the build action "content" and it seems i cannot read those files from my server. 我添加到插件项目的每个静态文件都获得构建操作“内容”,似乎我无法从我的服务器读取这些文件。 (see my previously answered question ). (见我之前回答的问题 )。 I have to manually select "Embedded Resource" on each file, so it is packed with the plugin dll. 我必须在每个文件上手动选择“Embedded Resource”,因此它包含了插件dll。
  2. I want to support Typescript for the plugins. 我想支持插件的Typescript。 The Typescript compiler generates javascript files in the same directory as the typescript-files. Typescript编译器在typescript-files所在的目录中生成javascript文件。 But the javascript files are not included in the project and therefore i have to include these in the plugin project and then set the correct build action. 但是javascript文件不包含在项目中,因此我必须将它们包含在插件项目中,然后设置正确的构建操作。 I don't want the plugin developers to do that all the time. 我不希望插件开发人员一直这样做。
  3. If the static files have the build action "enbedded resources", then the server can pickup these files by using the assembly.GetManifestResourceNames() method. 如果静态文件具有构建操作“enbedded resources”,则服务器可以使用assembly.GetManifestResourceNames()方法拾取这些文件。 This method returns the resources as a string. 此方法将资源作为字符串返回。 The path is not separated by \\ or / but with a dot instead. 路径不是由\\或/分隔,而是用点分隔。 So i am not able to distinguish between file path (this is relevant) or filename (also relevant to pickup the correct files), because the original filename can also have dots. 所以我无法区分文件路径(这是相关的)或文件名(也与拾取正确的文件相关),因为原始文件名也可以有点。

So i am starting to question the "class library" project type is right for my needs. 所以我开始质疑“类库”项目类型是否适合我的需求。 Is there a way to get around of my issues or do i have to use another project type? 有办法解决我的问题,还是我必须使用其他项目类型?

Thank you for any help! 感谢您的任何帮助!

Edit: Changed the question a little bit so it is better to understand. 编辑:稍微改变了一下这个问题,这样可以更好地理解。

You could make a zip package with the plugin dll and files. 你可以使用插件dll和文件制作一个zip包。 NuGet also uses this mechanism. NuGet也使用这种机制。 A .nupkg is also just a zip file. .nu​​pkg也只是一个zip文件。

I would start by looking at MEF (Managed Extensibility Framework). 我首先看一下MEF(Managed Extensibility Framework)。

MSDN information can be found here: https://msdn.microsoft.com/en-us/library/dd460648(v=vs.110).aspx MSDN信息可以在这里找到: https//msdn.microsoft.com/en-us/library/dd460648(v = vs.110).aspx

From that link you can get more information and I believe there is a tutorial as well. 从该链接可以获得更多信息,我相信还有一个教程。

Oh, for me it seems very simple. 哦,对我来说似乎很简单。

  1. Let the developer create the plugin freestyle and put all the additional files in a directory, let's call it extras 让开发人员创建插件自由式并将所有其他文件放在一个目录中,让我们称之为extras
  2. To implement the your interface they will need your assembly so I guess you will ship it via nuget, or just some link. 要实现您的界面,他们将需要您的程序集,所以我猜您将通过nuget或只是一些链接发送它。 No matter what the case, provide them with some powershell script what will be required to run before the final build 无论如何,请为他们提供一些powershell脚本,以便在最终构建之前运行
  3. The script would create zip archive from the extras directory and add it to the ClassLibrary project as EmbeddedResource. 该脚本将从extras目录创建zip存档,并将其作为EmbeddedResource添加到ClassLibrary项目中。
  4. As you mentioned earlier, you can access EmbeddedResource. 如前所述,您可以访问EmbeddedResource。 So all you would do is to unpack it and you would have the exact directory tree. 所以你要做的就是解压缩它,你就拥有了确切的目录树。

The best idea would be to provide project template with script included, and also the empty zip archive added as embedded resource (it will be easier to just pack the files in the script and replace the file), and pre-build action set to run the script. 最好的想法是提供包含脚本的项目模板,以及作为嵌入式资源添加的空zip存档(将脚本中的文件打包并替换文件将更容易),以及预构建操作集以运行剧本。

Am I missing something? 我错过了什么吗?

What about this. 那这个呢。

In your web application, you could add a function that loop into your plugin directory and find DLL implementing an Iplugin (name is up to you) interface. 在您的Web应用程序中,您可以添加一个循环到您的插件目录中的函数,并找到实现Iplugin(名称取决于您)接口的DLL。

The interface is defined in a class library that both your web application and plugins have to implement. 接口在类库中定义,您的Web应用程序和插件都必须实现。

You can use the Httpcontext Server mappath to read javascript and other files. 您可以使用Httpcontext Server mappath来读取javascript和其他文件。

Here is a very basic implementation 这是一个非常基本的实现

First, you have the plugin interface (a class library implemented both by the web application and the individual plugins) I implemented sample properties and methods... 首先,你有插件接口(由Web应用程序和各个插件实现的类库)我实现了样本属性和方法......

using System.Web;

public interface IPlugin
{
string Name { get; set; }
string Output { get; set; }
void Load(ref httpcontext Context);
void Dispose();
void Display();
}

Next, you have the Actual plugin class library we want to implement. 接下来,您有我们想要实现的Actual插件类库。

using System.Web;
using IPlugins;

public class AwesomePlugin : IPlugins.IPlugin
{

private string _Name = "AwesomePlugin";

private HttpContext _Context;
public string Name {
    get { return _Name; }
    set { _Name = value; }
}

public string Output {
    get { return "Yay !!!"; }
    set {
        throw new NotImplementedException();
    }
}

public void Display()
{
    throw new NotImplementedException();
}

public void Dispose()
{
    throw new NotImplementedException();
}


public void Load(ref Web.HttpContext Context)
{


}
}

Finally, you dynamically load your plugins so you can use them in your application. 最后,您可以动态加载插件,以便在应用程序中使用它们。

private Dictionary<string, IPlugins.IPlugin> _Plugins = new     Dictionary<string, IPlugins.IPlugin>();
public void LoadPlugins()
{
lock (static_LoadPlugins_IpluginType_Init) {
    try {
        if (InitStaticVariableHelper(static_LoadPlugins_IpluginType_Init)) {
            static_LoadPlugins_IpluginType = typeof(IPlugins.IPlugin);
        }
    } finally {
        static_LoadPlugins_IpluginType_Init.State = 1;
    }
}
string ServerPath = HttpContext.Current.Server.MapPath("~") + "Plugins";
dynamic Plugins = io.Directory.GetFiles(ServerPath);


foreach (string PluginPath in Plugins) {
    dynamic Assembly = system.Reflection.Assembly.LoadFile(PluginPath);

    Type PluginClass = Assembly.GetTypes.Where(T => T.GetInterface("IPlugin") != null).First;
    IPlugins.IPlugin MyPlugin = Activator.CreateInstance(PluginClass);
    MyPlugin.Load(httpcontext.Current);
    _Plugins.@add(PluginClass.ToString, MyPlugin);


}

}
static bool     InitStaticVariableHelper(Microsoft.VisualBasic.CompilerServices.StaticLocalInitFlag flag)
{
if (flag.State == 0) {
    flag.State = 2;
    return true;
} else if (flag.State == 2) {
    throw new Microsoft.VisualBasic.CompilerServices.IncompleteInitialization();
} else {
    return false;
}
}

That way, you can implement whatever you want in your plugin. 这样,您就可以在插件中实现您想要的任何内容。 I believe you could load your plugins in a separate appdomain with restricted permissions to everything. 我相信你可以在一个单独的appdomain中加载你的插件,对所有内容都有限制权限。

The files (Javascript / CSS / Html) should be available by accessing the full path of the file. 通过访问文件的完整路径,应该可以使用文件(Javascript / CSS / Html)。

string ServerPath = HttpContext.Current.Server.MapPath("~") + "Plugins";

If the resources is embedded into the plugin DLL, you could read the stream from the loaded assembly or let the plugin manage its own embedded files. 如果资源嵌入到插件DLL中,您可以从加载的程序集中读取流,或让插件管理自己的嵌入文件。

For question Number 2, you can use 对于问题2,您可以使用

MS Build MS Build

to change the contenttype during build process. 在构建过程中更改contenttype。 You have to make yourself confident with MS Build 你必须让自己对MS Build充满信心

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM