#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