Как надежно определить вызывающую сборку в .NET 4.0 - PullRequest
0 голосов
/ 22 июня 2011

В .NET 3.5 и ниже, следующий (немного грубый пример) работает довольно хорошо:

Сборка A:

public static class ClassInAssemblyA
{
    public static string GetCallingAssemblyLocation()
    {
        return System.Reflection.Assembly.GetCallingAssembly().GetName(false).CodeBase;
    }
}

Сборка B:

public class ClassInAssemblyB
{
    public string AssemblyName { get; private set; }

    public ClassInAssemblyB()
    {
        AssemblyName = ClassInAssemblyA.GetCallingAssemblyLocation();
    }
}

Сборка C:

var assemblyName = new ClassInAssemblyB().AssemblyName;
Assert.That(assemblyName.Contains("AssemblyB"));

К сожалению, CLR .NET 4.0, по-видимому, оптимизирован для встраивания кода AssemblyA в AssemblyB, поэтому вышеприведенный тест фактически проходит при выполнении в режиме отладки, но не работает в режиме выпуска . По сути, невозможно воспроизвести ошибку во время перехода.

Один из способов остановить встраивание - это потребовать от вызывающей стороны добавлять атрибут [MethodImpl(MethodImplOptions.NoInlining)] каждый раз, когда они ссылаются на AssemblyA. Это хитрое решение, которое требует от вызывающего абонента знать внутреннюю работу библиотеки, и это не должно быть их проблемой, поэтому я не хочу идти по этому пути.

Существуют ли альтернативные способы выяснить во время выполнения, какое имя файла у вызывающей сборки ?

Ответы [ 2 ]

1 голос
/ 22 июня 2011

Не думаю, что есть какое-либо решение, кроме использования MethodImplOptions.NoInlining.См. Документацию для GetCallingAssembly , которая включает в себя почти этот точный сценарий.Также обратите внимание, что вам нужно добавить атрибут к и к методу в A, и к методу в B, поскольку встраивание любого в вызывающую сборку приведет к тому поведению, которое вы видите.

0 голосов
/ 07 мая 2013

Насколько я понимаю, JIT-компилятор всегда будет учитывать [Flags(MethodImplOptions.NoInlining)], за исключением , возможно, в случае, если вы пытаетесь проверить саморекурсивный вызов.

Это основано на

  1. документация к MethodImplOptions (которая, как кажется, вызывает хвостовую рекурсию как особый случай)
  2. цитата из спецификации CLI, обсуждаемой здесь:

http://bytes.com/topic/c-sharp/answers/509557-race-conditions-c-eventing

(который не обсуждал хвостовую рекурсию, насколько я читал)

...