Сборка. Влияние на производительность
Я работаю над компонентом, который выполняет предварительный метод любого интерфейса, зарегистрированного в ioc, и момент выполнения зависит от разных триггеров. Он должен иметь возможность сохранять действия, которые необходимо выполнить, в базу данных, поэтому я сохраняю имя метода, тип и список параметров (сериализованных в BLOB) в базу данных до тех пор, пока это не потребуется.
Когда триггер происходит, мне нужно выполнить метод на экземпляре типа. Поскольку я использую внедрение зависимостей, у меня есть имя интерфейса, сохраненное в базе данных (в формате "Namespace.IInterface, AssemblyName"
)
Бежать Resolve<IInterface>()
метод на контейнере ioc, мне нужен экземпляр его Type
:
Assembly assembly = System.Reflection.Assembly.Load(assemblyName);
Type service = assembly.GetType(typeName);
object instance = IOCContainer.Resolve(service);
Мои вопросы:
- Есть ли лучший способ получить экземпляр Type из его имени, если я уверен, что содержащая сборка уже загружена в домен приложения? (Я пробовал просто
Type.Load(typeName)
но получил ноль) - Если рассматриваемая сборка уже загружена, оптимизирует ли CLR этот процесс (использовать уже загруженную) или мне нужно вручную кэшировать список сборок, чтобы предотвратить влияние на производительность многократной загрузки одной и той же сборки снова и снова?
4 ответа
- Если
typeName
что вы используете, включает в себя имя сборки (что-то вродеMyNamespace.MyType, MyAssembly version=1.0.0.0,publicKeyToken=12345etc
) затемType.Load(typeName)
получит ваш тип, но не ноль; - CLR заботится о загрузке сборки только один раз (один раз для контекста, подробности здесь, в вашем случае контекст остается тем же, поэтому ответ заключается в том, что вы должны расслабиться и оставить кэширование до CLR:)).
Есть ли лучший способ получить экземпляр Type из его имени, если я уверен, что содержащая сборка уже загружена в домен приложения? (Я пытался просто с Type.Load(typeName), но получил нулевое значение)
Нет.
Если рассматриваемая сборка уже загружена, CLR оптимизирует этот процесс (используйте уже загруженную)
Да.
Каждая сборка загружается только один раз.
Если рассматриваемая сборка уже загружена, CLR оптимизирует этот процесс (используйте уже загруженную)
Ответ только на этот вопрос находится на шаге 2 статьи MSDN Как среда выполнения находит сборки:
Если запрошенная сборка также запрашивалась в предыдущих вызовах, в общеязыковой среде выполнения используется уже загруженная сборка. Это может иметь последствия при именовании сборок, составляющих приложение. Для получения дополнительной информации об именовании сборок см. Имена сборок.
Не имеет прямого отношения к вопросу, но также полезно:
Если предыдущий запрос на сборку завершился неудачно, последующие запросы на сборку не будут выполнены немедленно, без попытки загрузить сборку. Начиная с.NET Framework версии 2.0, ошибки привязки сборки кэшируются, и кэшированная информация используется для определения необходимости загрузки сборки.
Чтобы проверить влияние на производительность, я попытался загрузить одну и ту же сборку n раз. И обнаружил, что общая выделенная память растет с каждым вызовом.
Чтобы попробовать сделать следующее:
while (true)
{
Assembly assembly = Assembly.LoadFrom("abc.dll");
//monitor: AppDomain.CurrentDomain.MonitoringTotalAllocatedMemorySize
//memory growing with each call
}
=============
Затем я сделал это, чтобы убедиться, что загружаю сборку только один раз.
var typeName = "Namespace.ClassName, Namespace";
while (true)
{
var typeFound = Type.GetType(typeName);
if (typeName == null)
{
Assembly assembly = Assembly.LoadFrom("abc.dll");
}
//monitor: AppDomain.CurrentDomain.MonitoringTotalAllocatedMemorySize
//memory will not grow after first call
}