开发者

Modules Security in C# Windows Form Applications?

How can i separate my app开发者_如何学运维lications to different modules? End users will use only modules that they bought. Can i use that using plug-and-pluy?


You could to take a look into Managed Extensibility Framework to add modules dynamically.


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)


MS has an example and tools for this in their Shareware Starter Kit für C#. Download from here: 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.


If you don't want to use MEF, try this. 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):

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. In both folders was deployed Interfaces.dll on which my projects rely on. 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; but if you forget this your app won't work at all; so I decided to force dll deletion before searching and loading plugins.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜