Безопасность модулей в приложениях C # Windows Form? - PullRequest
1 голос
/ 05 февраля 2011

Как я могу разделить свои приложения на разные модули? Конечные пользователи будут использовать только те модули, которые они купили. Могу ли я использовать это с помощью plug-and-pluy?

Ответы [ 4 ]

2 голосов
/ 05 февраля 2011

Вы можете взглянуть на Managed Extensibility Framework для динамического добавления модулей.

1 голос
/ 05 февраля 2011

Да.

Вы можете динамически загружать сборки на основе общего интерфейса или атрибутов разметки.

Динамическая загрузка сборки

Возможно, вы захотитеисследовать составной блок приложений (CAB) (но у него есть кривая обучения)

0 голосов
/ 05 февраля 2011

Если вы не хотите использовать MEF, попробуйте это. Прежде всего определите (в библиотеке) ваши интерфейсы:

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

    public interface IPlugin02
    {
        void Calc2();
    }
}

Затем напишите ваши плагины (вероятно, сборки в файлах 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()"); }
    }
}

Наконец, создайте ваше приложение, которое загружает и использует ваши плагины:

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

Просто комментарий: мои решения (содержащие интерфейсы, плагины и приложение консоли тестирования) скомпилировали мое приложение в . \ Bin , а плагины в . \ Bin \ Plugins . В обеих папках был развернут Interfaces.dll , на который опираются мои проекты. Это серьезная проблема , помните (читайте комментарии в коде) !!! Таким образом, вы можете скомпилировать свои плагины, избегая, чтобы Interfaces.dll копировался в . \ Bin \ Plugins dir; но если вы забудете это, ваше приложение не будет работать вообще; поэтому я решил принудительно удалить DLL перед поиском и загрузкой плагинов.

0 голосов
/ 05 февраля 2011

MS имеет пример и инструменты для этого в своем Shareware Starter Kit для C #. Скачать отсюда: http://msdn.microsoft.com/en-us/library/cc533530.aspx

Это несколько устарело. Но если вы ищете бесплатные ресурсы (есть некоторые коммерческие решения), это все, что существует, без развития всей инфраструктуры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...