C#:使用"类库"插件项目

时间:2016-05-19 15:42:24

标签: c# asp.net visual-studio plugins typescript

这个问题跟随我的previous question。 我有一个c#ASP.NET应用程序,我想为插件提供支持。插件可以是自定义c#类,javascript,html,css,图像等。

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

  1. 我添加到插件项目的每个静态文件都会获得构建操作" content"似乎我无法从我的服务器读取这些文件。 (见我的previously answered question)。我必须手动选择"嵌入式资源"在每个文件上,所以它用插件dll打包。
  2. 我想支持插件的Typescript。 Typescript编译器在typescript-files所在的目录中生成javascript文件。但是javascript文件不包含在项目中,因此我必须将它们包含在插件项目中,然后设置正确的构建操作。我不希望插件开发人员一直这样做。
  3. 如果静态文件具有构建操作"嵌入资源",则服务器可以使用assembly.GetManifestResourceNames()方法拾取这些文件。此方法将资源作为字符串返回。路径不是由\或/分隔,而是用点分隔。所以我无法区分文件路径(这是相关的)或文件名(也与拾取正确的文件相关),因为原始文件名也可以有点。
  4. 所以我开始质疑"类库"项目类型适合我的需求。有没有办法解决我的问题,还是我必须使用其他项目类型?

    感谢您的帮助!

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

5 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

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

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

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

答案 2 :(得分:0)

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

  1. 让开发人员创建插件自由式并将所有其他文件放在一个目录中,让我们称之为extras
  2. 要实现您的界面,他们将需要您的程序集,所以我猜您将通过nuget或只是一些链接发送它。无论如何,请为他们提供一些powershell脚本,以便在最终构建之前运行。
  3. 该脚本将从extras目录创建zip存档,并将其作为EmbeddedResource添加到ClassLibrary项目中。
  4. 如前所述,您可以访问EmbeddedResource。所以你要做的就是解压缩它,你就拥有了确切的目录树。
  5. 最好的想法是提供包含脚本的项目模板,以及作为嵌入式资源添加的空zip存档(在脚本中将文件打包并替换文件会更容易),以及预构建操作设置为运行脚本。

    我错过了什么吗?

答案 3 :(得分:0)

这个怎么样?

在您的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中,您可以从加载的程序集中读取流,或让插件管理自己的嵌入文件。

答案 4 :(得分:0)

对于问题2,您可以使用

  

MS Build

在构建过程中更改contenttype。 你必须对自己MS Build

充满信心