C#:将"Class Library"项目用于插件



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

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

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

所以我开始质疑"类库"项目类型是否适合我的需求。有没有办法解决我的问题,或者我必须使用另一种项目类型?

谢谢你的帮助!

编辑:把问题改了一点,这样更好地理解。

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

我将从MEF(托管扩展框架)开始。

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

从这个链接你可以得到更多的信息,我相信还有一个教程。

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

  1. 让开发人员创建插件freestyle,并将所有附加文件放在一个目录中,我们称之为extras
  2. 为了实现你的接口,他们需要你的程序集,所以我想你会通过nuget或只是一些链接来发布它。无论在何种情况下,都要为他们提供一些powershell脚本,这些脚本在最终构建之前需要运行
  3. 该脚本将从extras目录创建zip存档,并将其作为EmbeddedResource添加到ClassLibrary项目中
  4. 如前所述,您可以访问EmbeddedResource。所以你所要做的就是打开它的包装,你就会得到确切的目录树

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

我是不是错过了什么?

这个怎么样。

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

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

您可以使用HttpcontextServer映射路径来读取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();
}

接下来,您将获得我们想要实现的实际插件类库。

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

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

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

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

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

对于问题2,您可以使用

MS构建

以在生成过程中更改内容类型。您必须让自己对MS Build 充满信心

最新更新