AssemblyResolve не запускается для зависимостей

Я уже некоторое время борюсь с событием AssenblyResolve. Я искал stackoverflow, гуглил и пробовал все, что я считаю нужным. Вот ссылки, наиболее близкие к моей проблеме (на мой взгляд):

  1. AssemblyResolve не вызывается, а FileNotFoundException вызывается во время сериализации

  2. Где обрабатывать событие AssemblyResolve в библиотеке классов?

У меня есть класс Bootstrapper со статическим методом (для ясности я удалю имеющийся у нас потокобезопасный код:

public static void Initialize()
{
    AppDomain.CurrentDomain.AssemblyResolve += CustomResolve;
}

private static Assembly CustomResolve(object sender, ResolveEventArgs args)
{
    // There is a lot code here but basicall what it does.
    // Is determining which architecture the computer is running on and
    // extract the correct embedded dll (x86 or x64). The code was based
    // on milang on GitHub (https://github.com/milang/P4.net). And it's the same
    // purpose we want to be able to load the x86 or x64 version of the perforce dll
    // but this time with the officially Perforce supported p4api.net.
    // Once the dll is extracted we assign it to the boostrapper
    Bootstrapper._p4dnAssembly = Assembly.LoadFile(targetFileName);

    // Make sure we can satisfy the requested reference with the embedded assembly (now extracted).
    AssemblyName reference = new AssemblyName(args.Name);
    if (AssemblyName.ReferenceMatchesDefinition(reference, Bootstrapper._p4dnAssembly.GetName()))
    {
        return Bootstrapper._p4dnAssembly;
    }
}

Я смог заставить код работать, если у меня есть простой класс с основным методом и статическим конструктором. Статический конструктор просто вызывает метод Boostrapper.Initialize(). После этого я мог использовать свою библиотеку, и она работала, как и ожидалось:

public static class Test
{
    static Test()
    {
        Bootstrapper.Initialize();
    }

    public static void Main()
    {
         // Using the library here is working fine. The AssemblyResolve event was
         // fired (confirmed by a breakpoint in Visual Studio)
    }
}

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

public static class Test
{
    static Test()
    {
        Bootstrapper.Initialize();
    }

    public static void Main()
    {
        Class1 myClass = new Class1();

        // The following line is using the code of the extracted library, but
        // The AssemblyResolve event is not fired (or fired before I register the  
        // callback) and therefore the library is not found : result  
        // BadImageFormatException() error could not load libary because one
        myClass.Connect();
    }
}

Похоже, № 2 из ссылок, которые я ранее указал, объясняют, что я вижу, но это не работает. Точка останова Visual Studio в обратном вызове AssemblyResove никогда не срабатывает.

Любая идея о том, что происходит?

Фрэнсис


person Francis P    schedule 26.10.2012    source источник


Ответы (2)


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

Проблема в основном заключается в том, что приложение пытается разрешить все сборки, необходимые для выполнения метода, в начале этого метода:

static void main(string[] args)
{
    // <-- here the app tries to resolve MyAssembly
    // and as MyAssembly.Class1 is not found, the app crashes

    // this next line is never called:
    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(ResolveAssembly);

    // class contained in an assemnly that we need to resolve
    MyAssembly.Class1 myClass = new MyAssembly.Class1();
}

Вот почему приведенное выше приведет к сбою: обработчик события ResolveAssembly никогда не будет вызван, потому что он никогда не подключался.

И именно поэтому работает приведенное ниже решение (как опубликовано ОП):

static void main(string[] args)
{
    Initialize();
    RealMain();
}

static void Initialize()
{
    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(ResolveAssembly);
}

static void RealMain()
{
   // <-- here the app tries to resolve MyAssembly
   // class contained in an assemnly that we need to resolve      
   MyAssembly.Class1 myClass = new MyAssembly.Class1();
   // and everything is OK
}
person Arie    schedule 23.09.2014

Кто-то ответил, но ответ был удален. Поэтому я не могу отметить это как ответ. В основном тот факт, что код не должен находиться за пределами «основного» метода, работает. Начиная с нового проекта, решите проблему, поэтому я думаю, у меня были проблемы с dll (вероятно, dll x86 в папке x64 или наоборот)

static void main(string[] args)
{
    Boostrapper.Initialize();
    RealMain();
}

static void RealMain()
{
    Class1 myClass = new Class1();
    myClass.Connect();
}
person Francis P    schedule 30.10.2012