7

我正在使用 Castle Windsor for 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 Castle 程序集,我得到:

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。

有任何想法吗?谢谢。

编辑

我发现了我认为的问题:

.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 进行子类化?

4

3 回答 3

2

I had some luck with this. To be honest, I'm not sure why, but I couldn't reproduce the problem described by Krzysztof. I suspect...maybe...it has something to do with the fact that my assemblies are SN'd...which required me to make an additional change...but once I did, I was able to get proxies resolved for internal classes (with public interfaces) in a SL test application.

The only change I had to make to the Castle.Core source was to make the fields ModuleScope.moduleBuilder and ModuleScope.moduleBuilderWithStrongName protected instead of private. But again, that was only necessary so that I could define a SN'd dynamic assembly in SL, which is disabled for SL by the ModuleScope in Castle.Core. So, now I have a custom ModuleScope as follows:

    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;
        }
    }

And a custom 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);
        }
    }

And a custom 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());
        }
    }

And the container setup:

        container = new WindsorContainer();

        container.Kernel.ProxyFactory = new DefaultProxyFactory();

我不太喜欢修改 Castle.Core 源,所以我真的很想听听您的想法 Krzysztof ...如果此解决方案不适用于其他测试用例,您是否可以只保护这些字段?

于 2010-11-17T01:11:11.020 回答
0

我可能完全不在这儿,但你不是在找IncludeNonPublicTypes()吗?

从文档中

注册非公共类型

默认情况下,只会注册从程序集外部可见的类型。如果要包含非公共类型,则必须先指定程序集,然后调用 IncludeNonPublicTypes

container.Register(
    AllTypes.FromThisAssembly()
        .IncludeNonPublicTypes()
        .BasedOn<NonPublicComponent>()
);
于 2010-11-11T17:41:48.480 回答
0

原因是 Silverlight 安全模型不允许我们为内部类型构建代理,即使使用 InternalsVisibleTo。

于 2010-11-11T21:52:47.240 回答