Страницы

Поиск по вопросам

Показаны сообщения с ярлыком plugin. Показать все сообщения
Показаны сообщения с ярлыком plugin. Показать все сообщения

суббота, 11 апреля 2020 г.

Система плагинов

#c_sharp #plugin #рефлексия

                    
Захотелось научиться работать с отражением и вот этим всем.
Начал с простенького, решил написать подключаемый плагин, который автоматически подгрузится
из именной папки.

Что бы не мучиться с отражением методов и прочей нечистью на ум конечно же приходит
наследование и полиморфизм.
То есть мне нужен какой-то базовый класс с начальным функционалом от которого будут
наследоваться все другие плагины.

То есть нужно сделать отдельную библиотеку с апи, которую будут использовать обе
стороны (программа и плагин).

public interface IPlugin
{
    void Loaded();
}


Вот такой класс придумал в этой библиотеке.
Теперь я могу спокойно ее подключать к плагину и наследоваться.

public class Test : IPlugin
{
    #region Implementation of IPlugin

    public void Loaded() => Console.WriteLine( "Hello World" );

    #endregion
}


Вот у меня уже две библиотеки, одна с моим апи, другая его использует.
Теперь мне нужно как-то загрузить сборку с плагином и использовать его методы.
Вот тут мне и нужна помощь.

Так как библиотека плагина использует другую библиотеку с апи, я не смогу ее так
просто загрузить, так как выскочит ошибка мол либе не хватает референсов. Как правильно
загрузить плагин указав что сборка которая ему нужна уже загружена в программу?

Вот код которым я пытаюсь что-то наколдовать:

private static void Main ( string[] args )
    {
        var pluginsPath = $"{Directory.GetCurrentDirectory()}\\Plugins";
        var files = Directory.GetFiles( pluginsPath , "*.dll" );

        foreach ( var file in files )
        {
            Console.WriteLine( $"Trying load: {file}" );
            Assembly assembly;

            try { assembly = Assembly.Load( file ); }
            catch ( Exception ex )
            {
                Console.WriteLine( ex.Message );
                continue;
            }

            var types =
                assembly.GetTypes().Where( type => type.IsClass && type.GetInterface(
nameof( IPlugin ) ) != null );

            foreach ( var type in types )
            {
                var plugin = Activator.CreateInstance( type ) as IPlugin;

                if ( plugin == null )
                {
                    Console.WriteLine( "Null" );
                    continue;
                }

                plugin.Loaded();
            }
        }
    }


Падает еще на первом try с сообщением: 


  Необработанное исключение типа "System.IO.FileLoadException" в mscorlib.dll
  Дополнительные сведения: Не удалось загрузить файл или сборку "C:\Users\anweledig\Documents\Visual
Studio 2015\Projects\Anweledig\ConsoleApplication\bin\Debug\Plugins\TestPlugin.dll"
либо одну из их зависимостей. Данное имя сборки или база кода недействительны. (Исключение
из HRESULT: 0x80131047)

    


Ответы

Ответ 1



Вы можете просто загрузить другую библиотеку. Все ее зависимости будут автоматически загружены. Проблема может быть только в случае, если библиотека лежит не в той же папке, в которой лежит ваше приложение, и вы при этом загружаете ее через Assembly.LoadFrom. Чтобы это обойти, вам нужно указать рантайму что зависимости надо искать в папке плагина, а не в папке вашего приложения. Тогда можно будет использовать обычный Assembly.Load и заодно заработает станадартный механизм загрузки сборок. Для этого можно использовать создание аппдомена с указанием AppDomainSetup.ApplicationBase Т.е. схема примерно такая: У вас есть базовая dll для плагинов - MyApp.SDK, в ней базовый класс (а лучше - интерфейс): public abstract class Plugin { public abstract void Loaded(); public abstract void Unload(); } в ней же код загрузки и вызова плагина (для простоты) public static class PluginInvoker { public static void InvokePlugin() { var pluginAssembly = Assembly.Load("SomePlugin"); var pluginType = pluginAssembly.GetTypes().Where(t => typeof(Plugin).IsAssignableFrom(t)).Single(); Plugin plugin = (Plugin)pluginType.GetConstructor(new Type[0]).Invoke(null); plugin.Loaded(); } } есть реализация этого плагина в SomePlugin.dll: public class Test: MyApp.SDK.Plugin { public override void Loaded() { Console.WriteLine("Loaded"); } public override void Unload() { Console.WriteLine("Unloaded"); } } в SomePlugin есть референс на MyApp.SDK. И есть главное приложение, в котором есть ссылка на MyApp.SDK, но нет ссылки на SomePlugin: static void Main(string[] args) { AppDomainSetup setup = new AppDomainSetup(); setup.ApplicationBase = @"C:\Projects\MyApp\SomePlugin\bin\Debug\"; AppDomain pluginDomain = AppDomain.CreateDomain("plugin", null, setup); pluginDomain.DoCallBack(PluginInvoker.InvokePlugin); } ApplicationBase задает папку, откуда AppDomain будет загружать сборки - т.к. это папка плагина, то все, на что он ссылается, будет корректно загружено. Если плагины подгружаются из подпапки приложения (например, из Plugins), то в вместо AppDomainSetup.ApplicationBase можно использовать AppDomainSetup.PrivateBinPath. Если же при этом плагины вообще не планируется выгружать, и все плагины лежат в одной папке (без подпапок на каждый из плагинов) - то можно обойтись без отдельного AppDomain, просто дописав путь к папке с плагинами в секцию app.config/. код примера на github: https://github.com/PashaPash/PluginLoadSample

воскресенье, 15 марта 2020 г.

Создание ПО с плагинами

#c_sharp #delphi #plugin #desktop #рефлексия


По долгу службы требуется реализация довольно сложного десктопного ПО. Как одно из
требований — плагины (подключаемые модули), которые могут быть очень разнообразными:
от определения новых типов данных до работы с интерфейсом (добавление форм, кнопок
и т.п.). Разумеется, также требуются аналитика, обработка данных, сохранение в разные
БД и т.д.

Платформы для выбора — C# или Delphi (т.к. есть прототип, реализующий 90% потребного
функционала, но в режиме «спагетти»).

Если с Delphi всё понятно — средство загрузки/выгрузки плагинов делать руками, то
вот с C# не всё так прозрачно.

Пока что быстрый поиск показал следующие варианты:


MEF: довольно просто в реализации, но нельзя изолировать плагины в отдельных AppDomain
(что довольно-таки важно, это существенное архитектурное преимущество .NET вообще и
шарпа в частности);
MAF: переусложнено, замудрённо, и, с виду, уже не поддерживается. С другой стороны —
мощная изоляция;
самостоятельная реализация на reflection (например, так), с возможностью загрузки
в AppDomain и прочим. Но придётся много велосипедить, чего в общем-то не хочется.


Есть ещё варианты? Может, что-то не было учтено?

UPD: добавил ссылки.
    


Ответы

Ответ 1



Для C# есть встроенное готовое решение от Microsoft: System.Addin. Позволяет конфигурировать плагины так, чтобы использовать их в том же AppDomain'е, или в выделенном другом, или каждый в своём, или вообще в отдельном процессе. Не понимаю, почему везде советуют MEF. Это решение именно для расширяемости: код, который вы загружаете, считается доверенным и очень мало отличается от основного кода приложения, поэтому возможности выгрузки и управление правами напрочь отсутствуют. Самостоятельный велосипед на reflection написать можно, но придётся довольно серьёзно разбираться в тонкостях наподобие Fusion и Load context, так что я бы не советовал тратить время. Обновление: Ага, System.Addin — это то, что вы называете MAF.

Ответ 2



Зависит от специфических требований к вашей системе. Так ли нужна изоляция в отдельный домен? Если код ваших плагинов не предполагает взаимодействия с Native библиотеками, то и исключения, выбрасываемые из плагина, не поломают вашу программу целиком. Вы вполне можете их перехватить, по стеку установить плагин-виновник и предложить пользователю в следующий раз не загружать его. Ну да, не так круто, как в динамике выгрузить домен, но зато насколько меньше возни. Вот Студия же работает именно так. Ну а если ваши плагины способны нарушить работу процесса на уровне ОС, то ляжет весь процесс приложения вместе с CLR и доменами. Поэтому с MAF я бы не связывался. Что до остального, могу посоветовать Mono.Addins. По возможностям превосходит MEF. Документация есть, но не исчерпывающая. Примеров маловато. Также есть система ICSharpCode.Core, используемая в SharpDevelop, она тоже мощная, есть исходники (сам шарпдевелоп). Но документации почти нет, и она сильно устарела.

вторник, 28 января 2020 г.

Работа с иконками в Android Studio

#android #android_studio #plugin #graphics


Как из одной иконки сделать 5 для всех DPI экрана? Например, я нарисовал какой-то
элемент для проекта в максимальном разрешении для xxxhdpi. Есть ли в Android Studio
какие-то стандартные инструменты, чтобы сделать из этого элемента остальные разрешения
под все экраны? Или может плагин какой, если нет стандартных способов.
    


Ответы

Ответ 1



Необходимо проделать следующие шаги в Android Studio: Найти папку res и кликнуть по ней правой кнопкой мыши Выбрать New -> Image Assett Указать путь до иконки в Image Path и настроить дополнительные параметры по желанию Нажать Next и Finish После чего у вас в проекте появятся папки mipmap-xxx для каждого разрешения, в которых будут лежать ваши иконки.

Ответ 2



Да, есть хороший плагин: Можно еще на сайте сгенерить. Или вот здесь

среда, 22 января 2020 г.

Расширение для VISUAL STUDIO, которое подкрашивает ключевые слова запросов

#sql #visual_studio #plugin


Запросы находятся в ресурсах в виде *.sql файлов, а в месте вызова находятся инструкции
такого вида:

Properties.Resources.Query


При наведении курсора на Query высвечивается текст запроса, но подсветки синтаксиса нет.

Есть ли какие-нибудь плагины, которые исправляют данную проблему?

Можно конечно открывать файлы в обозреватели VS и там все подсвечивается, но это
не всегда удобно, так как плодятся лишние вкладки.
    


Ответы

Ответ 1



Такой вопрос уже обсуждался на англоязычном SO, и в качестве варианта было предложено вот это расширение для Visual Studio 2012, которое путём редактирования манифеста можно попробовать завести и в более новых версиях Visual Studio. Однако, обсуждение сошлось на том, что работать это не может корректно, так как синтаксический анализатор не в состоянии определить, является ли строка SQL кодом или просто строкой и может работать некорректно. В качестве альтернативы, можно использовать .sql-файлы с кодом SQL в проекте (которые в принципе подсвечиваются довольно неплохо), используя их так: string sql = System.IO.File.ReadAllText("путь к файлу .sql"); Все ответы взяты из оригинального англоязычного обсуждения.

Ответ 2



Как по мне то Syntax Highlighting Pack подходит наилучше, потому что поддерживает очень много языков программирования и работает с Visual Studio 2015, 2017

воскресенье, 12 января 2020 г.

Портирование jQuery-плагинов на React.js

#javascript #jquery #plugin #reactjs


Последнее время, React.js набирает огромную популярность в веб-разработке. Очень
много проектов выбирают эту платформу. В процессе разработки приходит понимание того,
что jQuery-плагины, встроенные в React приложение, смотрятся несколько чужеродно. Мне,
как разработчику плагинов, интересна тема их портирования и у меня появилось несколько
вопросов:


Нужно ли это вообще? Насколько react-разработчики заинтересованы в портировании огромной
базы jQuery-плагинов на свою платформу?
Насколько стабилен React.js на текущий момент, планируются ли в ближайшем будущем
существенные изменения его концепции?
Имеет ли смысл создание изолированных react-плагинов в отрыве от конечного проекта,
и возможно ли это вообще?
Существуют ли какие-то паттерны, регламентирующие создание плагинов на react.js (подобные
тем, что существуют для jQuery)? И есть ли где-то подробные гайды по созданию таких
компонентов?
Есть ли какие-либо примеры рабочих react-плагинов?

    


Ответы

Ответ 1



Насколько react-разработчики заинтересованы в портировании огромной базы jQuery-плагинов на свою платформу? Выберете плагин, с которого вы бы начали и посмотрите в Google AdWords, нужен ли он кому-нибудь кроме Вас Насколько стабилен React.js на текущий момент, планируются ли в ближайшем будущем существенные изменения его концепции? Этот вопрос лучше задать на Github Issues Имеет ли смысл создание изолированных react-плагинов в отрыве от конечного проекта, и возможно ли это вообще? https://react.parts/web существует, значит это и имеет смысл и возможно Существуют ли какие-то паттерны, регламентирующие создание плагинов на react.js (подобные тем, что существуют для jQuery)? React.js Component Guideline Есть ли какие-либо примеры рабочих react-плагинов? https://react.parts/web P.S. Про существование React.js узнал из Вашего вопроса

суббота, 11 января 2020 г.

Кастомный горизонтальный скролл с animate.css

#html #jquery #css #plugin


Есть такой код:



$(window).load(function(){
	// Horizontal scroll
    if($(".js-page-scroll").length){
        $(".js-page-scroll").mCustomScrollbar({
        	axis:"x",
            theme:"dark-3",
            // scrollbarPosition: 'outside',
            advanced:{ autoExpandHorizontalScroll:true },

            callbacks:{
                    whileScrolling:function(){
                    	
                    	new WOW().init();
                        
                    }
                }
        });
    }
});
main {
    display: flex;
    flex-flow: row nowrap;
    align-items: center;
    align-content: center;
    justify-content: space-between;
}

section {
    display: block;
    width: 300px;
    border: 1px solid #000;
    padding: 1rem;
}

.js-page-scroll {
    width: 100%;
    overflow-x: auto;
}


  

  


  
  

1

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

2

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

3

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

4

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

5

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

Использую кастомный скролл (горизонтальный) - malihu custom scrollbar Для анимации - animate.css и wow.js Суть в том, что при горизонтальном скролле, текст в блоках появлялся (анимировался) плавно и соответственно последовательно (как при использовании wow.js). Т.е. wow.js но для горизонтальной прокрутки. Вопрос: как настроить wow.js (или, возможно, есть какой другой плагин) для горизонтального скролла? || Как настроить animate.css для кастомного скролла (при прокрутке блоки появлялись плавно, последовательно)?


Ответы

Ответ 1



Можно сделать обычную проверку на наличие элемента в зоне видимости, без всяких доп плагинов. $(this).offset().left < windowWidth - проверяем вошел ли элемент в зону видимости "справа" $(this).offset().left > -$(this).width() - проверяем вошел ли элемент в зону видимости "слева" Если вошел, до добавляем ему класс анимации, если ушел, то удаляем $(window).load(function(){ var windowWidth = $(window).width(); var thisLeft, thisWidth; function animateBlocks(){ $('.animated').each(function(){ thisLeft = $(this).offset().left; thisWidth = $(this).width(); if(thisLeft < windowWidth && thisLeft > -thisWidth){ $(this).addClass('fadeInUp'); }else{ $(this).removeClass('fadeInUp'); } }); } animateBlocks(); // Horizontal scroll if($(".js-page-scroll").length){ $(".js-page-scroll").mCustomScrollbar({ axis:"x", theme:"dark-3", // scrollbarPosition: 'outside', advanced:{ autoExpandHorizontalScroll:true }, callbacks:{ whileScrolling:function(){ animateBlocks(); } } }); } }); main { display: flex; flex-flow: row nowrap; align-items: center; align-content: center; justify-content: space-between; } section { display: block; min-width: 300px; border: 1px solid #000; padding: 1rem; } .js-page-scroll { width: 100%; overflow-x: auto; }

1

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

2

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

3

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

4

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

5

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?



вторник, 7 января 2020 г.

Изолированное выполнение Java

#sandbox #java #plugin


Доброго времени суток!
Вопрос общего плана, так как пока пытаюсь собрать в кучу мысли и определится с инструментарием.
Есть (будет:)) ядро приложения, которое взаимодействует с файловой системой, базой
данных, сетью. Для увеличения его функционала планируется использование "модулей расширения".
Основная задача модулей - получить от ядра данные, каким-то образом их обработать,
вернуть результат.
Само собой, очень хочется, чтоб модули имели как можно меньше возможностей шариться
там, где им явно не разрешили...
Если бы речь не шла о кросс-платформе, я бы наверно удовлетворился *nix-chroot'ом
- каждой хрени по изолированной середе (+,возможно, по отдельному пользователю) и в
своих рамках хай творят, что хотят.
Вариант разработки своей интерпретируемой среды с кучей предметных объектов и языком..
наверно, в теории, тоже может рассматриваться, но уже попахивает извращениями в стиле 1С))
Вопрос - можно ли каким-либо образом запускать java-классы в среде... ну примерно
так, как это делает браузер для апплетов? Или может как-то можно уменьшить набор системных
классов для модуля (естественно предоставив аналогичные, но фильтруемые)...
Буду рад услышать идеи, соображения, ссылки на литературу...
Спасибо!    


Ответы

Ответ 1



Ну можно конечно извратиться и запустить 2 копии JVM, в одной JVM крутится ваше ядро, а во второй ваши плагины. Взаимодействие между ядром и плагинами организовать через RMI

Ответ 2



Похоже, вам пригодится кастомный ClassLoader, чтобы устанавить нужный ProtectionDomain. Ссылки: [1], [2].

среда, 1 января 2020 г.

Стилизация плагина `select2`

#javascript #jquery #css #plugin


Есть такой плагин select2. Хочу стилизовать его примерно так:



Но тут есть проблемы, когда я абсолютным позиционированием вывожу выбранные опции,
то и input выводится наружу. 

Можете подсказать каким путем мне идти, чтобы добиться такого результата как на картинке.



$(document).ready(function(){
  $('.__select2').select2({
        placeholder: 'Select an Industry',
        allowClear: false,
        tags: true,
        maximumSelectionLength: 5
    });
});











    


Ответы

Ответ 1



Не красиво, но задачу выполняет. $(document).ready(function(){ $('.__select2').select2({ placeholder: 'Select an Industry', allowClear: false, tags: true, maximumSelectionLength: 5 }); }); .select2-container--default .select2-selection--multiple .select2-selection__rendered { position: absolute; top: 100%; height: 0; overflow: visible !important; white-space: nowrap !important; } .select2-container--default .select2-selection--multiple .select2-selection__choice { float: none !important; display: inline-block; position: relative; } .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { position: absolute; right: -8px; top: -14px; } .select2-container .select2-search--inline { position: absolute; top: -100%; transform: translateY(-100%); /*тут через calc можно подровнять или через margin*/ width: 90% !important; } .select2-container--default .select2-search--inline .select2-search__field{ max-width: 100% !important; }

четверг, 26 декабря 2019 г.

Плагин для размытия любой области страницы в стиле iOS 7

#jquery #plugin #css #javascript


Однажды делая свой сайт мне захотелось сделать overlay'и так же как это сделала Apple
в своей iOS 7: вместо  какого либо background оставить его прозрачным, только лишь
размыть то, что находиться позади этого div'a и иногда слегка наложить полупрозрачный
цвет.  

Первое место куда я пошел это были форумы, и сколько я не пытался найти что то подобное,
я находил лишь не закрытые вопросы, но не ответы на них.
Поэтому остался лишь один вариант это сделать этот велосипед самому.
В результате очень долгих мучений, времени и усилий я все таки смог получить желаемый
результат. 

Потом мне пришла великолепная идея выложить это на GitHub.
Я его собрал в качестве плагина для jQuery.
Страница на GitHub.
Страница плагина.
Очень рад буду принимать ваши pull reqest'ы, issue, отзывы, звезды и так далее)))
Не примите за рекламу, просто мне кажется что плагин действительно нужный в наше
время, судя по стольким не закрытым вопросам на форумах, в большинстве своем "stackoverflow",
а по другому никто о нем не узнает.

    


Ответы

Ответ 1



Блурить по координатам нужно крайне редко, обычно это делается для конкретного элемента, так что css filters + polyfill самое оно; Вы делаете расширение для jQuery, то добавьте return this в конец, сейчас после вызова вашего метода, невозможно продолжить цеполчку вызовов jquery-методов; Внутри функции $.fn.blurBg вы получаете html, стирает его, а потом, на onrendered, заново вставляете. Это совсем плохо. Во первых, html2canvas работает асинхронно, поэтому элемент, с которым работает ваше расширение может быть за это время уже модифицирован. Во вторых, если в элементе находился тег script, то при использовании метода $.fn.html он опять будет выполнен, что может привести к нежелательным результатам, вот пример; Вместо метода position, нужно использовать offset; Если вы пишите для jQuery, то лучше использовать его, а не скатываться в native код; Заблуреный вариант, вставляется через background, что опять же может привести к нежелательным последствиям, если у элемента уже есть style="background: ..."; Если ресайзить страницу, то совсем печально :]

пятница, 5 июля 2019 г.

Система плагинов

Захотелось научиться работать с отражением и вот этим всем. Начал с простенького, решил написать подключаемый плагин, который автоматически подгрузится из именной папки.
Что бы не мучиться с отражением методов и прочей нечистью на ум конечно же приходит наследование и полиморфизм. То есть мне нужен какой-то базовый класс с начальным функционалом от которого будут наследоваться все другие плагины.
То есть нужно сделать отдельную библиотеку с апи, которую будут использовать обе стороны (программа и плагин).
public interface IPlugin { void Loaded(); }
Вот такой класс придумал в этой библиотеке. Теперь я могу спокойно ее подключать к плагину и наследоваться.
public class Test : IPlugin { #region Implementation of IPlugin
public void Loaded() => Console.WriteLine( "Hello World" );
#endregion }
Вот у меня уже две библиотеки, одна с моим апи, другая его использует. Теперь мне нужно как-то загрузить сборку с плагином и использовать его методы. Вот тут мне и нужна помощь.
Так как библиотека плагина использует другую библиотеку с апи, я не смогу ее так просто загрузить, так как выскочит ошибка мол либе не хватает референсов. Как правильно загрузить плагин указав что сборка которая ему нужна уже загружена в программу?
Вот код которым я пытаюсь что-то наколдовать:
private static void Main ( string[] args ) { var pluginsPath = $"{Directory.GetCurrentDirectory()}\\Plugins"; var files = Directory.GetFiles( pluginsPath , "*.dll" );
foreach ( var file in files ) { Console.WriteLine( $"Trying load: {file}" ); Assembly assembly;
try { assembly = Assembly.Load( file ); } catch ( Exception ex ) { Console.WriteLine( ex.Message ); continue; }
var types = assembly.GetTypes().Where( type => type.IsClass && type.GetInterface( nameof( IPlugin ) ) != null );
foreach ( var type in types ) { var plugin = Activator.CreateInstance( type ) as IPlugin;
if ( plugin == null ) { Console.WriteLine( "Null" ); continue; }
plugin.Loaded(); } } }
Падает еще на первом try с сообщением:
Необработанное исключение типа "System.IO.FileLoadException" в mscorlib.dll Дополнительные сведения: Не удалось загрузить файл или сборку "C:\Users\anweledig\Documents\Visual Studio 2015\Projects\Anweledig\ConsoleApplication\bin\Debug\Plugins\TestPlugin.dll" либо одну из их зависимостей. Данное имя сборки или база кода недействительны. (Исключение из HRESULT: 0x80131047)


Ответ

Вы можете просто загрузить другую библиотеку. Все ее зависимости будут автоматически загружены.
Проблема может быть только в случае, если библиотека лежит не в той же папке, в которой лежит ваше приложение, и вы при этом загружаете ее через Assembly.LoadFrom. Чтобы это обойти, вам нужно указать рантайму что зависимости надо искать в папке плагина, а не в папке вашего приложения. Тогда можно будет использовать обычный Assembly.Load и заодно заработает станадартный механизм загрузки сборок.
Для этого можно использовать создание аппдомена с указанием AppDomainSetup.ApplicationBase
Т.е. схема примерно такая:
У вас есть базовая dll для плагинов - MyApp.SDK, в ней базовый класс (а лучше - интерфейс):
public abstract class Plugin { public abstract void Loaded(); public abstract void Unload(); }
в ней же код загрузки и вызова плагина (для простоты)
public static class PluginInvoker { public static void InvokePlugin() { var pluginAssembly = Assembly.Load("SomePlugin"); var pluginType = pluginAssembly.GetTypes().Where(t => typeof(Plugin).IsAssignableFrom(t)).Single(); Plugin plugin = (Plugin)pluginType.GetConstructor(new Type[0]).Invoke(null); plugin.Loaded(); } }
есть реализация этого плагина в SomePlugin.dll:
public class Test: MyApp.SDK.Plugin { public override void Loaded() { Console.WriteLine("Loaded"); }
public override void Unload() { Console.WriteLine("Unloaded"); } }
в SomePlugin есть референс на MyApp.SDK.
И есть главное приложение, в котором есть ссылка на MyApp.SDK, но нет ссылки на SomePlugin:
static void Main(string[] args) { AppDomainSetup setup = new AppDomainSetup(); setup.ApplicationBase = @"C:\Projects\MyApp\SomePlugin\bin\Debug\";
AppDomain pluginDomain = AppDomain.CreateDomain("plugin", null, setup); pluginDomain.DoCallBack(PluginInvoker.InvokePlugin); }
ApplicationBase задает папку, откуда AppDomain будет загружать сборки - т.к. это папка плагина, то все, на что он ссылается, будет корректно загружено.
Если плагины подгружаются из подпапки приложения (например, из Plugins), то в вместо AppDomainSetup.ApplicationBase можно использовать AppDomainSetup.PrivateBinPath
Если же при этом плагины вообще не планируется выгружать, и все плагины лежат в одной папке (без подпапок на каждый из плагинов) - то можно обойтись без отдельного AppDomain, просто дописав путь к папке с плагинами в секцию app.config/
код примера на github: https://github.com/PashaPash/PluginLoadSample

среда, 5 июня 2019 г.

Создание ПО с плагинами

По долгу службы требуется реализация довольно сложного десктопного ПО. Как одно из требований — плагины (подключаемые модули), которые могут быть очень разнообразными: от определения новых типов данных до работы с интерфейсом (добавление форм, кнопок и т.п.). Разумеется, также требуются аналитика, обработка данных, сохранение в разные БД и т.д.
Платформы для выбора — C# или Delphi (т.к. есть прототип, реализующий 90% потребного функционала, но в режиме «спагетти»).
Если с Delphi всё понятно — средство загрузки/выгрузки плагинов делать руками, то вот с C# не всё так прозрачно.
Пока что быстрый поиск показал следующие варианты:
MEF: довольно просто в реализации, но нельзя изолировать плагины в отдельных AppDomain (что довольно-таки важно, это существенное архитектурное преимущество .NET вообще и шарпа в частности); MAF: переусложнено, замудрённо, и, с виду, уже не поддерживается. С другой стороны — мощная изоляция; самостоятельная реализация на reflection (например, так), с возможностью загрузки в AppDomain и прочим. Но придётся много велосипедить, чего в общем-то не хочется.
Есть ещё варианты? Может, что-то не было учтено?
UPD: добавил ссылки.


Ответ

Для C# есть встроенное готовое решение от Microsoft: System.Addin. Позволяет конфигурировать плагины так, чтобы использовать их в том же AppDomain'е, или в выделенном другом, или каждый в своём, или вообще в отдельном процессе.
Не понимаю, почему везде советуют MEF. Это решение именно для расширяемости: код, который вы загружаете, считается доверенным и очень мало отличается от основного кода приложения, поэтому возможности выгрузки и управление правами напрочь отсутствуют.
Самостоятельный велосипед на reflection написать можно, но придётся довольно серьёзно разбираться в тонкостях наподобие Fusion и Load context, так что я бы не советовал тратить время.

Обновление: Ага, System.Addin — это то, что вы называете MAF.

понедельник, 4 марта 2019 г.

Кастомный горизонтальный скролл с animate.css

Есть такой код:
$(window).load(function(){ // Horizontal scroll if($(".js-page-scroll").length){ $(".js-page-scroll").mCustomScrollbar({ axis:"x", theme:"dark-3", // scrollbarPosition: 'outside', advanced:{ autoExpandHorizontalScroll:true }, callbacks:{ whileScrolling:function(){ new WOW().init(); } } }); } }); main { display: flex; flex-flow: row nowrap; align-items: center; align-content: center; justify-content: space-between; } section { display: block; width: 300px; border: 1px solid #000; padding: 1rem; } .js-page-scroll { width: 100%; overflow-x: auto; }

1

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

2

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

3

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

4

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

5

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?


Использую кастомный скролл (горизонтальный) - malihu custom scrollbar
Для анимации - animate.css и wow.js
Суть в том, что при горизонтальном скролле, текст в блоках появлялся (анимировался) плавно и соответственно последовательно (как при использовании wow.js). Т.е. wow.js но для горизонтальной прокрутки.
Вопрос: как настроить wow.js (или, возможно, есть какой другой плагин) для горизонтального скролла? || Как настроить animate.css для кастомного скролла (при прокрутке блоки появлялись плавно, последовательно)?


Ответ

Можно сделать обычную проверку на наличие элемента в зоне видимости, без всяких доп плагинов.
$(this).offset().left < windowWidth - проверяем вошел ли элемент в зону видимости "справа"
$(this).offset().left > -$(this).width() - проверяем вошел ли элемент в зону видимости "слева"
Если вошел, до добавляем ему класс анимации, если ушел, то удаляем
$(window).load(function(){ var windowWidth = $(window).width(); var thisLeft, thisWidth; function animateBlocks(){ $('.animated').each(function(){ thisLeft = $(this).offset().left; thisWidth = $(this).width(); if(thisLeft < windowWidth && thisLeft > -thisWidth){ $(this).addClass('fadeInUp'); }else{ $(this).removeClass('fadeInUp'); } }); } animateBlocks(); // Horizontal scroll if($(".js-page-scroll").length){ $(".js-page-scroll").mCustomScrollbar({ axis:"x", theme:"dark-3", // scrollbarPosition: 'outside', advanced:{ autoExpandHorizontalScroll:true }, callbacks:{ whileScrolling:function(){ animateBlocks(); } } }); } }); main { display: flex; flex-flow: row nowrap; align-items: center; align-content: center; justify-content: space-between; } section { display: block; min-width: 300px; border: 1px solid #000; padding: 1rem; } .js-page-scroll { width: 100%; overflow-x: auto; }

1

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

2

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

3

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

4

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

5

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?


четверг, 29 ноября 2018 г.

Плагин для размытия любой области страницы в стиле iOS 7

Однажды делая свой сайт мне захотелось сделать overlay'и так же как это сделала Apple в своей iOS 7: вместо какого либо background оставить его прозрачным, только лишь размыть то, что находиться позади этого div'a и иногда слегка наложить полупрозрачный цвет.
Первое место куда я пошел это были форумы, и сколько я не пытался найти что то подобное, я находил лишь не закрытые вопросы, но не ответы на них. Поэтому остался лишь один вариант это сделать этот велосипед самому. В результате очень долгих мучений, времени и усилий я все таки смог получить желаемый результат.
Потом мне пришла великолепная идея выложить это на GitHub. Я его собрал в качестве плагина для jQuery. Страница на GitHub. Страница плагина. Очень рад буду принимать ваши pull reqest'ы, issue, отзывы, звезды и так далее))) Не примите за рекламу, просто мне кажется что плагин действительно нужный в наше время, судя по стольким не закрытым вопросам на форумах, в большинстве своем "stackoverflow", а по другому никто о нем не узнает.


Ответ

Блурить по координатам нужно крайне редко, обычно это делается для конкретного элемента, так что css filters + polyfill самое оно; Вы делаете расширение для jQuery, то добавьте return this в конец, сейчас после вызова вашего метода, невозможно продолжить цеполчку вызовов jquery-методов; Внутри функции $.fn.blurBg вы получаете html, стирает его, а потом, на onrendered, заново вставляете. Это совсем плохо. Во первых, html2canvas работает асинхронно, поэтому элемент, с которым работает ваше расширение может быть за это время уже модифицирован. Во вторых, если в элементе находился тег script, то при использовании метода $.fn.html он опять будет выполнен, что может привести к нежелательным результатам, вот пример Вместо метода position, нужно использовать offset Если вы пишите для jQuery, то лучше использовать его, а не скатываться в native код; Заблуреный вариант, вставляется через background, что опять же может привести к нежелательным последствиям, если у элемента уже есть style="background: ..." Если ресайзить страницу, то совсем печально :]