Какой `[InternalsVisibleTo]` для сборок .NET Framework и .NET Standard/Core framework?

У меня проблема с видимостью типа кросс-сборки/другой сборки.

У меня есть следующая программа (которую я подписываю/строгим именем). Он сообщает Castle DynamicProxy (я использую версию 4.2.1 пакета Castle.Core NuGet) создать прокси для моего интерфейса IFoo. Я также указываю, что мой internal class InterfaceProxyBase должен быть базовым классом для типа прокси.

Затем DynamicProxy использует System.Reflection.Emit для создания типа прокси. Но, видимо, System.Reflection.Emit.TypeBuilder не имеет доступа к InterfaceProxyBase.

// [assembly: InternalsVisibleTo("?")]
//                               ^^^
// What do I need here for my program to work both on the .NET Framework 4.5+
// and on .NET Core / .NET Standard 1.3+?

using Castle.DynamicProxy;

class Program
{
    static void Main()
    {
        var generator = new ProxyGenerator();

        var options = new ProxyGenerationOptions
            {
                BaseTypeForInterfaceProxy = typeof(InterfaceProxyBase)  // <--
            };

        var proxy = generator.CreateInterfaceProxyWithoutTarget(
                typeof(IFoo),
                options,
                new Interceptor());
    }
}

public interface IFoo { }

internal abstract class InterfaceProxyBase { }

internal sealed class Interceptor : IInterceptor
{
    public void Intercept(IInvocation invocation) { }
}

Unhandled Exception: System.TypeLoadException: Access is denied: 'InterfaceProxyBase'.
   at System.Reflection.Emit.TypeBuilder.TermCreateClass(RuntimeModule module, Int32 tk, ObjectHandleOnStack type)
   ...
   at Castle.DynamicProxy.ProxyGenerator.CreateInterfaceProxyWithoutTarget(Type interfaceToProxy, ProxyGenerationOptions options, IInterceptor[] interceptors)
   at Program.Main() in Program.cs

Итак, видимо мне нужен атрибут [assembly: InternalsVisibleTo] для собственной сборки/сборок фреймворка. Моя программа (на самом деле библиотека классов) предназначена как для .NET 4.5, так и для .NET Standard 1.3.

Какие атрибуты [assembly: InternalsVisibleTo] мне нужны (включая точные открытые ключи), чтобы мой код работал на упомянутых платформах/целях?


P.S.: Я знаю, что могу обойти проблему, просто сделав InterfaceProxyBase общедоступным и спрятав его с помощью [EditorBrowsable(Never)] для вида, но я действительно не хочу делать этот внутренний тип общедоступным, если в этом нет необходимости.

P.P.S.: Если публиковать внутренние компоненты для сборок фреймворка — действительно плохая идея с точки зрения безопасности, дайте мне знать, и я с радостью пересмотрю свой подход.


person stakx - no longer contributing    schedule 11.12.2017    source источник
comment
Вы не можете попробовать Castle.Core? Что в результате?   -  person Lex Li    schedule 12.12.2017
comment
@LexLi: это то, что я попробовал первым. Отображение внутренностей для Castle.Core не имеет заметного эффекта. Затем я взглянул на трассировку стека и увидел, что исключение вызывается TypeBuilder внутри фреймворка; не от Касла. Я ожидал, что разрешения перейдут из Castle во фреймворк (эти надоедливые LinkDemand штучки, которые я никогда не понимал), но, видимо, в наши дни это работает не так.   -  person stakx - no longer contributing    schedule 12.12.2017
comment
Похоже, вам нужно установить mscorlib для .NET Framework и System.Reflection.Emit для .NET Core, docs.microsoft.com/en-us/dotnet/api/ Но мне интересно, предлагает ли Castle вам лучший способ. Можете попробовать проверить, как TypeBuilder используется в Castle (из стека вызовов исключений)? Это может дать вам некоторые подсказки.   -  person Lex Li    schedule 12.12.2017
comment
@LexLi: Возможно, стоит попробовать. Очевидно, я уже пробовал mscorlib, System, System.Core и System.Reflection.Emit (на .NET Core), сложность заключается в том, чтобы знать, какие открытые ключи включать.   -  person stakx - no longer contributing    schedule 12.12.2017


Ответы (1)


Вы должны установить InternalsVisibleTo для DynamicProxyGenAssembly2:

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]

DynamicProxyGenAssembly2 — это временная сборка, созданная Castle.DynamicProxy. Эта сборка содержит сгенерированный тип прокси, который наследуется от вашего InterfaceProxyBase. Поэтому DynamicProxyGenAssembly2 должен иметь доступ к типу InterfaceProxyBase. Возможные варианты: добавить атрибут InternalsVisibleTo или сделать InterfaceProxyBase общедоступным.

person CodeFuller    schedule 22.12.2017
comment
Ах... конечно! У меня сложилось ложное впечатление, что сборки фреймворка не смогли получить доступ к InterfaceProxyBase, когда отказ в доступе на самом деле вызван отношением наследования между типом прокси-сервера интерфейса, сгенерированным в DynamicProxyGenAssembly2 и InterfaceProxyBase. Не могли бы вы добавить это как краткое объяснение к вашему ответу, тогда я отмечу его как принятый ответ. - person stakx - no longer contributing; 24.12.2017
comment
Я добавил это примечание к своему ответу. - person CodeFuller; 25.12.2017