繁体   English   中英

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

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

这个问题遵循我之前的问题 我有ac#ASP.NET应用程序,我想为插件提供支持。 插件可以是自定义c#类,javascript,html,css,图像等。

只要我的应用程序使用c#类扩展,我就没有问题,因为所有用户必须做的是在visual studio中创建一个新的“类库”项目并实现我提供的接口。 然后从中构建一个DLL并将其上传到我的服务器。 插件开发人员也可以将静态文件(html,js,css等)添加到这个项目中,但我发现了一些问题:

  1. 我添加到插件项目的每个静态文件都获得构建操作“内容”,似乎我无法从我的服务器读取这些文件。 (见我之前回答的问题 )。 我必须在每个文件上手动选择“Embedded Resource”,因此它包含了插件dll。
  2. 我想支持插件的Typescript。 Typescript编译器在typescript-files所在的目录中生成javascript文件。 但是javascript文件不包含在项目中,因此我必须将它们包含在插件项目中,然后设置正确的构建操作。 我不希望插件开发人员一直这样做。
  3. 如果静态文件具有构建操作“enbedded resources”,则服务器可以使用assembly.GetManifestResourceNames()方法拾取这些文件。 此方法将资源作为字符串返回。 路径不是由\\或/分隔,而是用点分隔。 所以我无法区分文件路径(这是相关的)或文件名(也与拾取正确的文件相关),因为原始文件名也可以有点。

所以我开始质疑“类库”项目类型是否适合我的需求。 有办法解决我的问题,还是我必须使用其他项目类型?

感谢您的任何帮助!

编辑:稍微改变了一下这个问题,这样可以更好地理解。

你可以使用插件dll和文件制作一个zip包。 NuGet也使用这种机制。 .nu​​pkg也只是一个zip文件。

我首先看一下MEF(Managed Extensibility Framework)。

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

从该链接可以获得更多信息,我相信还有一个教程。

哦,对我来说似乎很简单。

  1. 让开发人员创建插件自由式并将所有其他文件放在一个目录中,让我们称之为extras
  2. 要实现您的界面,他们将需要您的程序集,所以我猜您将通过nuget或只是一些链接发送它。 无论如何,请为他们提供一些powershell脚本,以便在最终构建之前运行
  3. 该脚本将从extras目录创建zip存档,并将其作为EmbeddedResource添加到ClassLibrary项目中。
  4. 如前所述,您可以访问EmbeddedResource。 所以你要做的就是解压缩它,你就拥有了确切的目录树。

最好的想法是提供包含脚本的项目模板,以及作为嵌入式资源添加的空zip存档(将脚本中的文件打包并替换文件将更容易),以及预构建操作集以运行剧本。

我错过了什么吗?

那这个呢。

在您的Web应用程序中,您可以添加一个循环到您的插件目录中的函数,并找到实现Iplugin(名称取决于您)接口的DLL。

接口在类库中定义,您的Web应用程序和插件都必须实现。

您可以使用Httpcontext Server mappath来读取javascript和其他文件。

这是一个非常基本的实现

首先,你有插件接口(由Web应用程序和各个插件实现的类库)我实现了样本属性和方法......

using System.Web;

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

接下来,您有我们想要实现的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)
{


}
}

最后,您可以动态加载插件,以便在应用程序中使用它们。

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;
}
}

这样,您就可以在插件中实现您想要的任何内容。 我相信你可以在一个单独的appdomain中加载你的插件,对所有内容都有限制权限。

通过访问文件的完整路径,应该可以使用文件(Javascript / CSS / Html)。

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

如果资源嵌入到插件DLL中,您可以从加载的程序集中读取流,或让插件管理自己的嵌入文件。

对于问题2,您可以使用

MS Build

在构建过程中更改contenttype。 你必须让自己对MS Build充满信心

暂无
暂无

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

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