【问题标题】:C#: use "Class Library" Project for pluginsC#:为插件使用“类库”项目
【发布时间】:2016-09-16 14:56:50
【问题描述】:

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

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

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

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

感谢您的帮助!

编辑:稍微改变了问题,以便更好地理解。

【问题讨论】:

  • 我很困惑。您正在谈论插件,但您正在谈论将文件添加到项目中。你的插件不应该是单独的项目吗?
  • @itsme86 OP 只是假设您已经阅读了他们之前的所有问题并了解有关他们项目的所有详细信息 - 就像一个积极的贡献者......公平的假设,但并不完全适合 SO。跨度>
  • 对不起。我说的是向插件项目添加文件。所以插件本身是一个构建 dll 的“类库”项目。此 dll 是将由服务器加载的插件。该插件不仅需要包含 c# 类,还需要包含 html 或 typescript 生成的 javascript 等静态文件。

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


【解决方案1】:

对于第二个问题,你可以使用

MS 构建

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

【讨论】:

    【解决方案2】:

    这个呢。

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

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

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

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

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

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

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

    【讨论】:

      【解决方案3】:

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

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

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

      我错过了什么吗?

      【讨论】:

        【解决方案4】:

        我将从查看 MEF(托管可扩展性框架)开始。

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

        您可以从该链接获得更多信息,我相信也有教程。

        【讨论】:

          【解决方案5】:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-12-22
            • 2014-08-31
            • 1970-01-01
            • 1970-01-01
            • 2017-07-04
            • 2014-07-11
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多