Внутренние замки Виндзора - PullRequest
7 голосов
/ 11 ноября 2010

Я использую Castle Windsor для SL v2.5.1.0. У меня есть прокси внутренние классы (интерфейсы, конечно, общедоступны, но реализация внутренняя, так что потребитель знает только об интерфейсе).

Я использую следующие атрибуты в моей сборке с внутренними классами

[assembly: InternalsVisibleTo("Castle.Core, PublicKey=002400000480000094000000060200000024000052534131000400000100010077F5E87030DADCCCE6902C6ADAB7A987BD69CB5819991531F560785EACFC89B6FCDDF6BB2A00743A7194E454C0273447FC6EEC36474BA8E5A3823147D214298E4F9A631B1AFEE1A51FFEAE4672D498F14B000E3D321453CDD8AC064DE7E1CF4D222B7E81F54D4FD46725370D702A05B48738CC29D09228F1AA722AE1A9CA02FB")]
[assembly: InternalsVisibleTo("Castle.Windsor, PublicKey=002400000480000094000000060200000024000052534131000400000100010077F5E87030DADCCCE6902C6ADAB7A987BD69CB5819991531F560785EACFC89B6FCDDF6BB2A00743A7194E454C0273447FC6EEC36474BA8E5A3823147D214298E4F9A631B1AFEE1A51FFEAE4672D498F14B000E3D321453CDD8AC064DE7E1CF4D222B7E81F54D4FD46725370D702A05B48738CC29D09228F1AA722AE1A9CA02FB")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]

В полном режиме .NET 4.0 со сборками .NET 4.0 Castle это работает нормально, и мои типы проксируются нормально. В Silverlight со сборками замка Silverlight я получаю:

Type ConsoleApplication4.MyTypeToBeProxied is not public. Can not create proxy for types that are not accessible.

Кроме того, просто при устранении проблемы добавление следующего, похоже, не имеет значения ...:

[assembly: InternalsVisibleTo("System.Core, PublicKey=00000000000000000400000000000000")]
[assembly: InternalsVisibleTo("System.Core, PublicKey=" +
"00240000048000009400000006020000002400005253413100040000010001008d56c76f9e8649" +
"383049f383c44be0ec204181822a6c31cf5eb7ef486944d032188ea1d3920763712ccb12d75fb7" +
"7e9811149e6148e5d32fbaab37611c1878ddc19e20ef135d0cb2cff2bfec3d115810c3d9069638" +
"fe4be215dbf795861920e5ab6f7db2e2ceef136ac23d5dd2bf031700aec232f6c6b1c785b4305c" +
"123b37ab")]

и я также проверил во время выполнения, что имя динамически размещенной сборки в SL по-прежнему фактически DynamicProxyGenAssembly2.

Есть идеи? Спасибо.

EDIT

Я нашел проблему, я думаю:

Замок для .NET 4.0 имеет:

private bool IsAccessible(Type target)
{
  //      ....
  return ((target.IsPublic || target.IsNestedPublic) || internalAndVisibleToDynProxy);

}

в DefaultProxyBuilder ... и SL 4 имеет

private bool IsAccessible(Type target)
{
    target.IsNested();
    return (target.IsPublic || target.IsNestedPublic);
}

Это что-то, что можно исправить в источнике Замка? Или мне нужно / я должен подразделить DefaultProxyFactory?

Ответы [ 3 ]

2 голосов
/ 17 ноября 2010

Мне повезло с этим.Если честно, я не уверен, почему, но я не мог воспроизвести проблему, описанную Кшиштофом.Я подозреваю ... возможно ... это как-то связано с тем фактом, что мои сборки SN'd ... что потребовало от меня внести дополнительные изменения ... но как только я это сделал, я смог получить разрешение проксидля внутренних классов (с открытыми интерфейсами) в тестовом приложении SL.

Единственное изменение, которое я должен был внести в Castle.Core, было сделать поля ModuleScope.moduleBuilder и ModuleScope.moduleBuilderWithStrongName защищенными, а не частными.Но опять же, это было необходимо только для того, чтобы я мог определить динамическую сборку SN в SL, которая отключена для SL в ModuleScope в Castle.Core.Итак, теперь у меня есть собственный ModuleScope следующим образом:

    private class StrongNameModuleScope : ModuleScope
    {
        public StrongNameModuleScope()
        {
            var assemblyName = new AssemblyName("DynamicProxyGenAssembly2");
            // copied from another one of my SN assemblies (plus GetName() on assembly is security critical so I can't pull it off the executing assembly)
            byte[] publicKey = Convert.FromBase64String(@"ACQAAASAAACUAAAABgIAAAAkAABSU0ExAAQAAAEAAQBvwWquPXQG9zfemS8uDsFdGDScOCSjZ9aFsQDtrrAqKzvlxEGMz3t9Q9M3X9NKqy1ouLZi+sX8yVDafX+UnygFWWfOBosw9nGwG61MTKEhEjdKH0rECahGIXY+ETdNY64HduuH/BIbEs/RDhrrH2hiqGrOGb6AghD1sZ6g0A1qkg==");
            assemblyName.SetPublicKey(publicKey);
            AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
            ModuleBuilder module = assembly.DefineDynamicModule("DynamicProxyGenAssembly2");
            moduleBuilder = module;
            moduleBuilderWithStrongName = module;
        }
    }

И пользовательский DefaultProxyBuilder:

    /// <summary>
    ///   A custom IProxyBuilder copies from the full .NET Castle implementation that allows for proxies of internal types where the InternalsVisibleToAttribute is applied.
    /// </summary>
    private class DefaultProxyBuilder : IProxyBuilder
    {
       ...
        // Methods
        public DefaultProxyBuilder()
            : this(new StrongNameModuleScope())
        {
        }
       ...
        private static bool IsAccessible(Type target)
        {
            bool isTargetNested = target.IsNested;
            bool isNestedAndInternal = isTargetNested && (target.IsNestedAssembly || target.IsNestedFamORAssem);
            bool internalAndVisibleToDynProxy = ((!target.IsVisible && !isTargetNested) || isNestedAndInternal) && InternalsHelper.IsInternalToDynamicProxy(target.Assembly);
            return ((target.IsPublic || target.IsNestedPublic) || internalAndVisibleToDynProxy);
        }
    }

И пользовательский DefaultProxyFactory:

  /// <summary>
    ///   A simple DefaultProxyFactory to wrap the modified DefaultProxyBuilder.
    /// </summary>
    private class DefaultProxyFactory : global::Castle.Windsor.Proxy.DefaultProxyFactory
    {
        public DefaultProxyFactory()
        {
            generator = new ProxyGenerator(new DefaultProxyBuilder());
        }
    }

Инастройка контейнера:

        container = new WindsorContainer();

        container.Kernel.ProxyFactory = new DefaultProxyFactory();

Мне не очень-то нравилось менять источники Castle.Core, поэтому мне бы очень хотелось услышать ваши мысли Кшиштоф ... возможно, вы могли бы просто сделать эти поляЗащищено, если это решение не работает для других тестовых случаев?

0 голосов
/ 12 ноября 2010

Причина в том, что модель безопасности Silverlight не позволяет нам создавать прокси для внутреннего типа, даже с InternalsVisibleTo.

0 голосов
/ 11 ноября 2010

Я могу быть совершенно не в курсе, но вы не ищете IncludeNonPublicTypes()?

Из документации :

Регистрация закрытых типов

По умолчанию будут зарегистрированы только те типы, которые видны снаружи сборки. Если вы хотите включить непубличные типы, вы должны сначала указать сборку, а затем вызвать IncludeNonPublicTypes

container.Register(
    AllTypes.FromThisAssembly()
        .IncludeNonPublicTypes()
        .BasedOn<NonPublicComponent>()
);
...