简体   繁体   English

C#Windows窗体应用程序中的模块安全性?

[英]Modules Security in C# Windows Form Applications?

How can i separate my applications to different modules? 如何将应用程序分离到不同的模块? End users will use only modules that they bought. 最终用户将仅使用他们购买的模块。 Can i use that using plug-and-pluy? 我可以通过即插即用的方式使用它吗?

您可以查看Managed Extensibility Framework来动态添加模块。

Yes. 是。

You can dynamically load assemblies based on a common interface or markup attributes. 您可以基于公共接口或标记属性动态加载程序集。

Dynamic assembly loading 动态装配加载

You might want to investigate Composite Application Block (CAB) (but it does have a learning curve) 您可能想研究复合应用程序块(CAB)(但它确实具有学习曲线)

MS has an example and tools for this in their Shareware Starter Kit für C#. MS在其C#的Shareware Starter Kit中提供了一个示例和工具。 Download from here: http://msdn.microsoft.com/en-us/library/cc533530.aspx 从此处下载: http : //msdn.microsoft.com/en-us/library/cc533530.aspx

It's somewhat old. 它有些旧了。 But if you are looking for free resources (there are some commercial solutions) this is all that afaik exists without developing the entire infrastructure from scratch. 但是,如果您正在寻找免费资源(有一些商业解决方案),那么afaik就是存在的,而无需从头开始开发整个基础架构。

If you don't want to use MEF, try this. 如果您不想使用MEF,请尝试此操作。 First of all define (in a library) your interfaces: 首先定义(在库中)您的接口:

namespace Interfaces
{
    public interface IPlugin01
    {
        string Name { get; }
        string Description { get; }
        void Calc1();
    }

    public interface IPlugin02
    {
        void Calc2();
    }
}

Then write your plugins (probably assemblies in DLL files) using classes implementing your interfaces (one or more): 然后使用实现您的接口的类(一个或多个)编写您的插件(可能是DLL文件中的程序集):

namespace Plugin01
{
    public class Class1 : Interfaces.IPlugin01,Interfaces.IPlugin02
    {
        public string Name { get { return "Plugin01.Class1"; } }
        public string Description { get { return "Plugin01.Class1 description"; } }
        public void Calc1() { Console.WriteLine("sono Plugin01.Class1 Calc1()"); }
        public void Calc2() { Console.WriteLine("sono Plugin01.Class1 Calc2()"); }
    }

    public class Class2 : Interfaces.IPlugin01
    {
        public string Name { get { return "Plugin01.Class2"; } }
        public string Description { get { return "Plugin01.Class2 description"; } }
        public void Calc1() { Console.WriteLine("sono Plugin01.Class2 Calc1()"); }
    }
}

Finally create your app that loads and uses your plugins: 最后,创建加载并使用插件的应用程序:

namespace Test
{
    class Program
    {
        /// ------------------------------------------------------------------------------            
        /// IMPORTANT: 
        /// you MUST exclude Interfaces.dll from being copied in Plugins directory,
        /// otherwise plugins will use that and they're not recognized as using
        /// the same IPlugin interface used in main code.
        /// ------------------------------------------------------------------------------            
        static void Main(string[] args)
        {
            List<Interfaces.IPlugin01> list1 = new List<Interfaces.IPlugin01>();
            List<Interfaces.IPlugin01> list2 = new List<Interfaces.IPlugin01>();

            List<Interfaces.IPlugin01> listtot = GetDirectoryPlugins<Interfaces.IPlugin01>(@".\Plugins\");

            Console.WriteLine("--- 001 ---");
            foreach(Interfaces.IPlugin01 plugin in list1)
                plugin.Calc1();

            Console.WriteLine("--- 002 ---");
            foreach (Interfaces.IPlugin01 plugin in list2)
                plugin.Calc1();

            Console.WriteLine("--- TOT ---");
            foreach (Interfaces.IPlugin01 plugin in listtot)
                plugin.Calc1();
            Console.ReadLine();
        }

        public static List<T> GetFilePlugins<T>(string filename)
        {
            List<T> ret = new List<T>();
            if (File.Exists(filename))
            {
                Assembly ass = Assembly.LoadFrom(filename);
                foreach (Type type in ass.GetTypes())
                {
                    if (!type.IsClass || type.IsNotPublic) continue;
                    if (typeof(T).IsAssignableFrom(type))
                    {
                        T plugin = (T)Activator.CreateInstance(type);
                        ret.Add(plugin);
                    }
                }
            }
            return ret;
        }
        public static List<T> GetDirectoryPlugins<T>(string dirname)
        {
            /// To avoid that plugins use Interfaces.dll in their directory,
            /// I delete the file before searching for plugins.
            /// Not elegant perhaps, but functional.
            string idll = Path.Combine(dirname, "Interfaces.dll");
            if (File.Exists(idll)) File.Delete(idll);

            List<T> ret = new List<T>();
            string[] dlls = Directory.GetFiles(dirname, "*.dll");
            foreach (string dll in dlls)
            {
                List<T> dll_plugins = GetFilePlugins<T>(Path.GetFullPath(dll));
                ret.AddRange(dll_plugins);
            }
            return ret;
        }
    }

Just a comment: my solutions (containing interfaces, plugins and test console app) compiled my app in .\\bin and plugins in .\\bin\\Plugins . 只需评论一下:我的解决方案(包含界面,插件和测试控制台应用程序)在。\\ bin中编译了我的应用程序,在。\\ bin \\ Plugins中编译了插件 In both folders was deployed Interfaces.dll on which my projects rely on. 在两个文件夹中都部署了我的项目所依赖的Interfaces.dll This is a serious problem , remember (read comments in code) !!! 这是一个严重的问题 ,请记住(阅读代码注释)! So you can compile your plugins avoiding that Interfaces.dll is copied in .\\bin\\Plugins dir; 因此,您可以编译插件,避免将Interfaces.dll复制到。\\ bin \\ Plugins dir;中。 but if you forget this your app won't work at all; 但是,如果您忘记了这一点,您的应用程序将根本无法运行; so I decided to force dll deletion before searching and loading plugins. 因此,我决定在搜索和加载插件之前强制删除dll。

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

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