Подтвердить что ты не робот

Инициализировать библиотеку при загрузке сборки

У меня есть DLL библиотеки .net, которая действует как функциональная библиотека. Существует множество статических типов вместе со статическими методами.

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

Когда сборка загружается, есть ли способ обеспечить выполнение определенного метода? Что-то вроде AppDomain.AssemblyLoad, но вызываемое автоматически из самой сборки. Я думал, что может быть что-то вроде AssemblyAttribute, который можно использовать?

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

Спасибо!

4b9b3361

Ответ 1

Зачем вам нужны все данные для загрузки до того, как они будут использованы, а не только тогда, когда используется первый тип, который нуждается в нем?

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

Ответ 2

Да, есть - вид.

Используйте превосходную небольшую полезность by Einar Egilsson, InjectModuleInitializer.

Запустите этот исполняемый файл как шаг пост-сборки, чтобы создать небольшую функцию .cctor(функцию инициализации модуля), которая вызывает статическую функцию void, которая не принимает никаких параметров. Было бы неплохо, если бы компилятор дал нам возможность создавать .cctor(), к счастью, нам редко нужна эта возможность.

Однако это не полная замена DllMain. CLR только вызывает эту функцию .cctor до любых методов, вызванных в вашей сборке, а не при сборке. Таким образом, если вам нужно что-то сделать при сборке, вам нужно, чтобы код загрузки вызывал метод напрямую или использовал подробный hack Ia fooobar.com/questions/221112/...

Ответ 3

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

У меня была аналогичная проблема, и я решил ее, создав ассемблерный атрибут 'InitializeOnLoad' с параметром Type. Затем в основном исполняемом файле я добавил тривиальный обработчик AppDomain.AssemblyLoaded, который сканирует недавно загруженную сборку для вышеупомянутого атрибута и вызывает на них System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor().

[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
public class InitializeOnLoadAttribute : Attribute
{
    Type type;

    public InitializeOnLoadAttribute(Type type) { this.type = type; }

    public Type Type { get { return type; } }
}

// somewhere very early in main exe initialization
AppDomain.CurrentDomain.AssemblyLoad += new AssemblyLoadEventHandler(AssemblyInitializer);

static void AssemblyInitializer(object sender, AssemblyLoadEventArgs args)
{
    // force static constructors in types specified by InitializeOnLoad
    foreach (InitializeOnLoadAttribute attr in args.LoadedAssembly.GetCustomAttributes(typeof(InitializeOnLoadAttribute), false))
        System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(attr.Type.TypeHandle);
}

Дополнительно, если вы боитесь, что сборки могли быть проложены до того, как вы перехватите событие AssemblyLoad, вы можете просто запустить AppDomain.GetAssemblies() и вызвать для них "инициализатор".

Ответ 4

Возможно - просто добавьте статический конструктор в класс <Module>. Я не знаю, как это сделать без модификации IL.