Страницы

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

суббота, 30 ноября 2019 г.

Срезанные углы блока

#html #css #svg


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

Я создал срез с помощью clip-path, но рамка блока срезается так же, как и он сам.
В итоге выходит так: 





html,
body,
.bdiv,
.mainblock {
    height: 100%;
    width: 100%;
    overflow: hidden;
}
.bdiv {
    display: table;
}
.mainblock {
    display: table-cell;
    vertical-align: middle;
}
.mainblock>div {
    position: relative;
    width: 500px;
    background: #444;
    margin: 0 auto;
}
.content {
    padding: 10px 30px;
    text-align: center;
    font-size: 16px;
    font-family: sans-serif;
    color: ddd;
}
.head-text {
    clip-path: polygon(460px 0, 100% 30px, 100% 100%, 0 100%, 0 0);
    font-size: 18px;
    color: #eee;
    border: 5px solid #fff;
    background: #333;
}
.cont-text {
    background: #000;
}
.cont-text>form input {
    padding: 5px;
    width: 40%;
}


Приветствую!
Можно, конечно, добавить абсолютный блок-линию как рамку поверх среза, но по-моему так не делается. Но как тогда? Мне нужно 2 таких среза, один как на картинке, а второй слева внизу.


Ответы

Ответ 1



html, body, .bdiv, .mainblock { height: 100%; width: 100%; overflow: hidden; } .bdiv { display: table; } .mainblock { display: table-cell; vertical-align: middle; } .mainblock>div { position: relative; width: 500px; /* background: #444; */ margin: 0 auto; } .content { padding: 10px 30px; text-align: center; font-size: 16px; font-family: sans-serif; color: #ddd; } .head-text { -webkit-clip-path: polygon(0 0, 90% 0, 100% 30px, 100% 100%, 10% 100%, 0 15px); clip-path: polygon(0 0, 90% 0, 100% 30px, 100% 100%, 10% 100%, 0 15px); font-size: 18px; color: #eee; background: url(https://www.noupe.com/wp-content/uploads/2009/10/pattern-13.jpg) center no-repeat; } .box { background: #fff; -webkit-clip-path: polygon(0 0, 90% 0, 100% 30px, 100% 100%, 10% 100%, 0 25px); clip-path: polygon(0 0, 90% 0, 100% 30px, 100% 100%, 10% 100%, 0 25px); padding: 5px; } .cont-text { background: #000; } .cont-text>form input { padding: 5px; width: 40%; } body { background: #444; }
Приветствую!


Ответ 2



Такой вот еще вариант svg: html, body, .bdiv, .mainblock { height: 100%; width: 100%; overflow: hidden; } .bdiv { display: table; } .mainblock { display: table-cell; vertical-align: middle; } .mainblock>div { position: relative; width: 500px; background: #444; margin: 0 auto; } .content { padding: 10px 30px; text-align: center; font-size: 16px; font-family: sans-serif; color: ddd; } .head-text { font-size: 18px; color: #eee; padding: 15px 30px; position: absolute; z-index: 2; top: 0; left: 0; right: 0; bottom: 0; } .cont-text { background: #000; } .cont-text>form input { padding: 5px; width: 40%; } .top { position: relative; height: 50px; } .top-bg { max-width: 100%; width: 100%; }
Приветствую!


Ответ 3



SVG - решение
Приветствую! Привет Пока
Здесь три кнопки меню выполнены с помощью трех патчей. Эти же патчи входят в маску, которая служит для того, чтобы стал виден фон. Решение универсальное, так как не нужно будет подбирать каждый раз окраску кнопок и их обводку. Она всегда будет гармонировать с выбранным фоном страницы. Для проверки замените фон или откройте сниппет на полный просмотр. Попробуйте заменить фон на другую картинку. На кнопки я сделал ховер, в принципе нетрудно добавить к ним ссылки. Все элементы в одном блоке SVG. Его лучше добавить в Html страничку инлайн. Update 23.08.2017 Доработка примера по замечаниям в комментариях автора вопроса При наведении на текст ссылка теряет фон до тех пор пока курсор не выйдет за пределы блока и обратно. И я все так и не понял как сделать анимированный фон определенному блоку SVG Данный эффект происходил из-за того, что текст в блоках не входил в группу, для которой был применен селектор :hover. Решил эту проблему объединением блока и текста в одну группу. Привет Добавлена анимация фона и текста при помощи изменения прозрачности #p1:hover, #p2:hover, #p3:hover{ fill:dodgerblue; color:white; opacity:1; -webkit-transition: opacity 0.5s; transition: opacity 0.8s ease-in-out; } #p1, #p2, #p3 { opacity:0.5; -webkit-transition: opacity 0.5s; transition: opacity 0.8s ease-in-out; } Ниже, доработанный пример: body { background: url('https://i.pinimg.com/originals/22/06/1e/22061e28e591fb82b41a151d64cefe55.jpg') no-repeat; background-size: cover; } height: 100%; width: 100%; overflow: hidden; .bdiv { display: table; } .container { position: relative; width: 500px; margin: 0 auto; } #p1:hover, #p2:hover, #p3:hover{ fill:dodgerblue; color:white; opacity:1; -webkit-transition: opacity 0.5s; transition: opacity 0.8s ease-in-out; } #p1, #p2, #p3 { opacity:0.5; -webkit-transition: opacity 0.5s; transition: opacity 0.8s ease-in-out; }
Приветствую! Привет Пока


Ответ 4



Решение с вложенным дивом с таким же clip-path: .content { padding: 10px 30px; text-align: center; font-size: 16px; font-family: sans-serif; color: ddd; } .head-text { font-size: 18px; color: #eee; background: #333; } .inborder { position: absolute; top: 5px; right: 5px; bottom: 5px; left: 5px; clip-path: inherit; } .border { position: relative; clip-path: polygon( 95% 0, 100% 45%, 100% 100%, 5% 100%, 0 55%, 0 0 ); background: red; min-height: 50px; }
Приветствую!


Наложение background только на текст

#css #css3 #вёрстка #svg


Есть текст. На него надо наложить background так, чтобы он был только на тексте.
То есть все, что не текст, было прозрачным. Думаю через svg сделать наложение картинки
на текст, но не знаю, как сделать все прозрачным, кроме букв. Сложность в том, что
на каждой букве должны быть не разные картинки, а одна цельная
    


Ответы

Ответ 1



svg { width: 6em; height: 1.5em; font: 900 500%/1.2 'Arial Black', sans-serif; } text { fill: url(#sea); } Ваш текст!!!

Ответ 2



Обратите внимание на проблему кроссбраузерности. * { margin: 0; padding: 0; } div { font: 900 normal 450%/100vh sans-serif; text-transform: uppercase; text-align: center; background-image: url("https://i.stack.imgur.com/zN1F6.jpg"); background-size: cover; -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }
Lorem ipsum


Зачем мы реализовываем IEquatable, если Equals() есть в Object?

#c_sharp #net


Разбирая тему обобщений (по Шиелду 4.0), потребовалось написать обобщённый  метод,
который вернет логическое значение true, если в массиве содержится некоторое значение.
Далее в книге поясняется, что так как T - обобщённый тип, то для сравнения  объектов
обобщённого типа  необходимо что бы класс этих объектов реализовывал интерфейс IEquatable
с параметром T или IEquatable. Написано так же, что в данных интерфейсах определен
метод для сравнения Equals(). Отсюда сразу же несколько вопросов:

Во-первых, почему для сравнения объектов обобщённого типа  нам вообще необходимо
реализовывать какие-либо интерфейсы? Метод Equals() относится к методам определённым
в Object => есть в каждом объекте. Я понял что для сравнения объектов в данном примере
нужно реализовать описанные выше интерфейсы, но я не понял, ПОЧЕМУ это нужно сделать.

Во-вторых, по Шиелду, как я написал выше, для сравнения объектов в обобщённом методе
предлагается реализовать Equtable с параметром T или IEqutable. Один параметризирован,
другой нет. Вопрос - какой в каком случае необходимо использовать?

Далее Шиелд в своей книге демонстрирует пример метода, который проверяет, находится
ли в массиве некоторое значение. Вот этот метод:

 public static bool IsIn(T what, T[] obs) where T : IEquatable
    {
        foreach(T v in obs)
        {
            if (v.Equals(what))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }


Тут так же есть два вопроса.

Во-первых, начну с того, что данный метод не работает. Студия выдает ошибку компиляции
"Не все ветви метода возвращают значение". Я несколько раз перепроверял написанный
код, но ошибка остается. Как это исправить?

Во-вторых, я не уверен, правильно ли я понял, что сигнатура данного метода подразумевает,
что в данный метод могут быть переданы только объекты тех типов, которые реализовывают
интерфейс IEquatable? Другими словами, если я захочу передать в метод массив каких
нибудь студентов, и найти в нём Васю Пупкина, то мой класс студента должен выглядить
следующим образом?

class Student : IEquatable
{
    public string Name;
    public string Surname;

    public bool Equals(T other)
    {
        //some code for compare
        return false;
    }
}


Прошу последовательно ответить на все вопросы. Спасибо 
    


Ответы

Ответ 1



Equals(object obj) появился в .NET в самом начале, а тогда еще не было дженериков. До введения дженериков в .NET 2.0, переопределение метода Equals(object obj) в большинстве случаев выглядело приблизительно так: public bool override Equals(object obj) { if (obj == null) return false; if (obj is MyClass) { MyClass other = (MyClass)obj; // сравниваем this и other } return false; } Получается, в большинстве случаев, объекты разных типов не могут быть равны. Что бы упростить жизнь, придумали интерфейс IEquatable, в котором можно сразу сравнивать 2 объекта, без проверок их типов (что тоже занимает некоторое время). По-хорошему теперь вы должны реализовать IEquatable для всех классов, которые можно сравнивать. При этом вы должны не забывать про переопределение старого Equals, для совместимости. Можно делать например вот так: public bool override Equals(object obj) { return Equals(obj as MyClass); } public bool Equals(MyClass other) { if (other== null) return false; // сравниваем объекты }

Ответ 2



Интерфейс IEquatable<> был придуман для того чтобы избегать лишней упаковки значимых типов при сравнении. До тех пор, пока все радовались объектам и использовали только их - у метода object.Equals(object) особых недостатков не было (лишнее приведение типов особо страшным недостатком не является). Но когда в языке появились обобщенные типы - все стало куда хуже. Попытка вызвать метод object.Equals(object other) для значимого типа приводит к тому, что: нулевой параметр (this) упаковывается и размещается в куче, первый параметр (other) упаковывается и размещается в куче, оба параметра распаковываются обратно и сравниваются, упакованные копии параметров забываются (и в следующий раз упаковка будет происходить заново). Вообще говоря, обобщенные типы придумали именно для того чтобы избегать лишних упаковок структур, поэтому необходимость упаковывать их только для того чтобы сравнить - катастрофа. Фактически, обобщенная коллекция System.Collections.Generics.Dictionary<,> из-за постоянных упаковок может работать даже хуже чем более старый вариант System.Collections.Hashtable. Поэтому и был придуман новый интерфейс, который позволяет сравнить два значения без приведения типов (и, как следствие, без упаковки). Теперь про ваш метод. Начну с того, что рекомендация из книги не совсем правильная: в стандартной библиотеке принято другое соглашение относительно подобных методов. Вместо того чтобы требовать реализации IEquatable<>, можно воспользоваться классом EqualityComparer<>, который внутри использует либо IEquatable<>, либо старый метод object.Equals если первый недоступен. Кроме того, желательно давать возможность передать в метод любую реализацию IEqualityComparer<> (например, для сравнения строк без учета регистра). Вот так будет правильнее: public static bool IsIn(T what, T[] obs, IEqualityComparer comparer = null) { if (comparer == null) comparer = EqualityComparer.Default; foreach(T v in obs) { if (comparer.Equals(what, v)) { return true; } } return false; } (Ну и про вторую ошибку в методе я уже писал тут: В условном операторе выполняются обе ветки // поиск по массиву не работает) С такой реализацией метода его можно использовать как с простыми классами (объекты таких классов сравниваются просто по ссылке): class Student { public string Name; public string Surname; } так и с более продвинутыми: sealed class Student : IEquatable { public readonly string Name; public readonly string Surname; public Student(string name, string surname) { Name = name; Surname = surname; } public override bool Equals(object other) => Equals(other as Student); public bool Equals(Student other) { if (this == other) return true; if (other == null) return false; if (Name != other.Name) return false; if (Surname!= other.Surname) return false; return true; } public override int GetHashCode() { unchecked { // https://stackoverflow.com/a/263416/4340086 int hash = 2166136261; hash = (16777619 * hash) ^ (Name?.GetHashCode() ?? 0); hash = (16777619 * hash) ^ (Surname?.GetHashCode() ?? 0); return hash; } } }

Ответ 3



Насчет "Не все ветви метода возвращают значение": если obs пустой, то код внутри foreach никогда не выполнится, следовательно метод не встретит ни одного оператора return. поэтому ошибка. Насколько я понимаю, код метода должен быть таким: public static bool IsIn(T what, T[] obs) where T : IEquatable { foreach(T v in obs) { if (v.Equals(what)) { return true; } } return false; } Да, сигнатура данного метода подразумевает, что в данный метод могут быть переданы только объекты тех типов, которые реализовывают интерфейс IEquatable.

Как избавиться от deadlock при использовании mutex?

#c++ #многопоточность


В первом потоке так:

mutex1.lock();
mutex2.lock();


Во втором так:

mutex2.lock();
mutex1.lock();


Проблема в том, что эти мьютексы находятся в разных классах, скажем Parent и Child,
они вызывают методы друг друга, но ничего не знают о внутреннем устройстве друг друга
(но если надо, их можно научить, но только как?). Мьютексы защищают какие-то внутренние
данные соответствующих классов.

Это происходит при вложенных вызовах:

Callstack - thread 1

10. mutex2.lock();
 9. child.method2();
 8. mutex1.lock();
 7. parent.method1();
....


Callstack - thread 2

10. mutex1.lock(); 
 9. parent.anotherMethod();
 8. mutex2.lock();
 7. child.someMethod();
....


Может есть какой-то паттерн для такой проблемы.
    


Ответы

Ответ 1



Чтобы избавиться от дедлоков, можно использовать функцию std::lock. Она принимает несколько мьютексов, и лочит их с помощью специального алгоритма который позволяет избежать дедлоков. Применять ее следует таким образом: std::lock(mutex1, mutex2); std::lock_guard guard1(mutex1, std::adopt_lock); std::lock_guard guard2(mutex2, std::adopt_lock); Или наоборот, сначала создать lock_guard, а потом залочить: std::lock_guard guard1(mutex1, std::defer_lock); std::lock_guard guard2(mutex2, std::defer_lock); std::lock(mutex1, mutex2);

Ответ 2



Обновление: В вашем случае, когда у каждого класса свой мьютекс, и проблема лишь в порядке вызовов, я бы очень не рекомендовал вызывать чужой код под блокировкой. Именно потому, что этот код имеет полное право залочить какой-то другой мьютекс. Вызов чужого кода под залоченным мьютексом — практически всегда опасность deadlock'а. Попробуйте реорганизовать код так, чтобы он выглядел следующим образом: void obj1.method1() { { std::lock_guard g1(mutex1); // работаем с данными/запоминаем их } // только здесь мы имеем право вызвать объект, который мы не контролируем obj2.method2(); } Вы не можете выбраться из этой ситуации. Классы, использующие общие мьютексы, должны кооперироваться. Часто проблема решается таким образом: мьютексы перенумеровываются, и если код хочет взять несколько мьютексов, он обязан брать их в порядке возрастания номеров. С другой стороны, можно уменьшить гранулярность блокировки, и использовать один мьютекс вместо обоих (если это допустимо в рамках вашей задачи). Также, вы можете попытаться избежать проблемы двойного мьютекса тем, что разделите работу с блокируемыми объектами на части/сущности: сначала залочите один мьютекс и извлечёте нужные данные, затем отпустите этот мьютекс и залочите другой, используя при работе со вторым объектом локально сохранённые данные. Ещё один подход, завоёвывающий популярность — избавиться по возможности от разделяемых данных, и работать как можно больше с локальными данными. Резюме: общего решения не существует. Выкручивайтесь.

Ответ 3



Вам уже ответили очень много полезного, хотелось бы добавить еще пару моментов : в случае, когда работа с данными постороена таким образом, что никак не избежать захватов двух мьютексов, советуют предопределить очередность захвата этих мьютексов, и во всех потоках придерживаться этой очередности; в тех случаях, когда архитектура не позволяет предопределить очередность захвата мьютексов, можно использовать std::try_lock(), которая в случае невозможности захвата мьютекса, возвращает управление. Таким образом, если поток захватил первый мьютекс, но не может захватить второй, - он может освободить первый, выполнить какую-то другую рутинную работу (вместо того, чтобы висеть на одном из мьютексов), и вернуться к попытке захвата этих мьютексов вновь.

Настроить консоль phpStorm, чтобы были доступны unix-команды (как в Git bash)

#windows #phpstorm #консоль #git_bash


Почему в command line tool phpStorm не работают команды ls, pwd, mkdir и др.?

В обычной cmd эти команды тоже не работают. Зато в консоли git bash работают. php,
git, composer — работают везде. Но это, я так понимаю, потому что прописано в переменной
PATH.

В чем отличие консольных утилит и как сделать так, чтобы команды работали?
    


Ответы

Ответ 1



По-умолчанию терминалом для PhpStorm является стандартный терминал windows cmd.exe. Для того чтобы настроить в PhpStorm bash терминал нужно изменить соответствующую настройку: -login и -i нужны для загрузки конфигурационных файлов и включения интерактивного режима. Терминал можно кастомизировать. Для этого в домашней директории ~ необходимо создать файл .bash_profile. К примеру: #Алиасы команд alias ls="ls -CF --color --show-control-chars" alias ll='ls -l' alias l='ls -CF' #Алиасы для опечаток alias cd..="cd .." alias ..="cd .."

Ответ 2



Официальная документация по настройке и использованию внедрённого локального терминала в PhpStorm. На русском не нашёл.

Ответ 3



У меня немного по-другому, путь к командному файлу: C:\Users\\AppData\Local\GitHub\PortableGit_\git-cmd.exe По этому пути в настройках терминала запустился git-овский.

Как сделать запрет на повтор?

#sqlite


Проблема такая, если занесли запись через запрос 'INSERT INTO' в таблицу, и второй
раз допустим случайно с таким же названиям, то данные не добавляются и это хорошо,
НО сам 'id' увеличивается в значении, каждой раз на одиницю, если совпадают названия
, что в моем случаи мне не подходит , возможно ли как-то это решить ?

Параметры таблицы

CREATE TABLE "content" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE,
"title" TEXT NOT NULL, 
"category" INTEGER NOT NULL,
"directians" TEXT NOT NULL,
"time" INTEGER,
"img" TEXT,
"autor" TEXT,
"datetime" DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE ("title") ON CONFLICT REPLACE)

    


Ответы

Ответ 1



Если значение ID увеличивается на единицу, то значит что данные, на самом деле, добавляются, а если быть точнее, то вновь добавляемые данные заменяют предыдущие значения. Об этом поведении говорит строка: UNIQUE ("title") ON CONFLICT REPLACE А для того, чтобы запретить добавление одинаковых данных и соответственно увеличения ID на единицу, нужно просто заменить поведение при конфликтных случаях с этого: UNIQUE ("title") ON CONFLICT REPLACE на вот это: UNIQUE ("title") ON CONFLICT IGNORE Таким образом, вновь добавляемые данные будут игнорироваться и добавление не сработает.

Ответ 2



На php $sth = $db->prepare("SELECT COUNT(*) FROM content WHERE title=?"); $sth->execute(array($title)); $result = $sth->fetchColumn(); if ($result) { $db->prepare("UPDATE ..."); } else { $db->prepare("INSERT ..."); } На mysql CREATE TABLE content ( id INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL UNIQUE, title VARCHAR(255) NOT NULL, UNIQUE (title)); INSERT INTO content (title) VALUES ('1st Street'); INSERT INTO test.Content (title) VALUES ('1st Street') ON DUPLICATE KEY UPDATE title='2st Street'; Индекс не меняется, проверял лично на MySql.

Ответ 3



Причина увеличения Id банальна, в схеме таблицы которую вы привели задекларировано поведение при возникновении конфликта обновлять запись, то есть добавить новую и удалить старую. От этого и возникает изменение Id записи. Нужно изменить ограничение "title" поля таблицы. В зависимости от поведения которое вы хотите получить нужно либо откатывать всю транзакцию или только конфликтующую инструкцию и уже потом обрабатывать в коде исключение (ссылка на документацию): UNIQUE ("title") ON CONFLICT ROLLBACK или UNIQUE ("title") ON CONFLICT ABORT "ON CONFLICT ABORT" - это поведение по умолчанию в sqlite Полное описание структуры таблицы: CREATE TABLE "content" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE, "title" TEXT NOT NULL, "category" INTEGER NOT NULL, "directians" TEXT NOT NULL, "time" INTEGER, "img" TEXT, "autor" TEXT, "datetime" DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE ("title") ON CONFLICT ABORT) Если это тот случай когда нельзя изменить схему таблицы (хотя наврядли), то нужно перенести проверку существования уникального "title" в код, но это несёт свои риски в многопоточной записи в таблицу.

Ответ 4



Хм... Может быть реализовывать по банальному по типу аналогии простых cms движков. Проверять на существования запись по title При создании записи, возвращать созданный автоинкремент (IDENT_CURRENT, LAST_INSERT_ID) и при следующих запросах обновлять запись или зная что авто инкремент мы получили сообщить о том что запись существует. Также можно сделать защиту на стороне клиента от повторных случайных нажатий с помощью javascript. Сделав кнопку не активной в течении N секунд.

Ответ 5



Не сильно знаком с SQLite, но вот что удалось нагуглить: Можно попробовать контролировать автоинкремент самостоятельно, например, через COALESCE вот так: INSERT OR REPLACE INTO "content" (id, title, category, directians, time, img, autor, datetime) VALUES( COALESCE( SELECT id FROM "content" WHERE title={title}, --если такой id существует оставляем его SELECT last_insert_rowid() FROM "content" -- если нет, вставляем по автоинкременту ), {title}, {category}, {directians}, {time}, {img}, {autor}, {datetime} ) source

Ответ 6



Правильно сделать - это оставить как есть т.е если id - увеличивается когда даже запрос не прошел -это нормально, если вам нужен порядковый номер то вы можете добавить дополнительное поле для этого, или если при выводе нужно нумеровать записи...то сортируете по id а номер пишите просто порядковый номер строки из выборки - так правильней. Но, если вам нужно по какимто из своих соображений именно так , то решение следующее: INSERT INTO CONTENT (id, title) SELECT max(id) + 1, 'your value' from content

Ограничить возможности стороннего класса C#

#c_sharp #классы #модульность #песочница


Имеется (модульное) игровое приложение - арена, в нем реализован абстрактный класс
(или интерфейс) для игрока. Игроков (игровые ИИ) наследуют от указанного класса и разрабатывают
сторонние разработчики и предоставляют в виде скомпилированного dll.
Есть ли вообще возможность ограничить возможности этой сторонней dll? Ну, например
защититься от "FORMAT C:" или от пересылки данных по сети, чтения с диска и т. д.
Пусть даже этот класс падает в этом случае - тогда игроку просто засчитывается техническое
поражение.

Какой день бьюсь, но, хоть убейте, никак не пойму, как заставить это работать.
Как сделать чтобы все сторонние игроки работали в песочнице? Сейчас есть примерно
такой код:

static class PlayersHost
{
    static public List Players;

    static public void LoadPlayers()
    {
        Players = new List();

        var files = Directory.EnumerateFiles(Path.Combine(Environment.CurrentDirectory,
"Players"), "*.dll");
        foreach (var file in files)
        {
            try
            {
                var asm = Assembly.LoadFrom(file);
                var types = asm.GetTypes();
                foreach (var type in types)
                {
                    try
                    {
                        IPlayer player = (IPlayer)Activator.CreateInstance(type);
                        players.Add(player);
                    }
                    catch { }
                }
            }
            catch { }
        }
    }
}


Потом я просто при старте приложения загружаю всех игроков:

PlayersHost.LoadPlayers();


и пользуюсь полученной коллекцией, например:

var player = PlayersHost.Players[0];
try { player.PrepareToPlay(); } catch { }


Нужно решение с использованием AppDomain
    


Ответы

Ответ 1



Для изолирования частично доверенного кода в .NET предусмотрен механизм ограничения доступа в рамках AppDomain - это называется Sandbox (запуск в песочнице). AppDomain.CreateDomain( string friendlyName, Evidence securityInfo, AppDomainSetup info, PermissionSet grantSet, params StrongName[] fullTrustAssemblies); Информация о том, как его использовать, а также ряд дополнительных соображений и нюансов подробно описаны в этой статье на MSDN: https://msdn.microsoft.com/ru-ru/library/bb763046(v=vs.110).aspx

Ответ 2



Альтернативным, более высокоуровневым решением может быть использование System.AddIn. Это фреймворк, более сложный, чем использование AppDomain, но он предоставляет больше возможностей. В частности, он позволяет автоматически находить загруженные add-in'ы, и загружать их по вашему желанию в текущий AppDomain в отдельный, специальный AppDomain для компонент, которым вы не доверяете каждую компоненту в отдельный AppDomain в отдельный внешний процесс каждую компоненту в отдельный AppDomain общего внешнего процесса. При этом протокол взаимодействия остаётся тем же самым. При этом объекты, которые переходят через границу между основным кодом и add-in'ами, должны быть сериализуемыми. К сожалению, полновесный пример не вписывается в формат ответа, но хороший пример есть в документации: Add-in overview Walkthrough: Creating an Extensible Application