城堡温莎InternalsVisibleTo Silverlight

时间:2010-11-11 16:11:41

标签: .net silverlight-4.0 castle-windsor castle-dynamicproxy

我正在使用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。

有什么想法吗?感谢。

修改

我发现了我认为的问题:

Castle for .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);
}

这可以在Castle源中修复吗?或者我是否需要/应该对DefaultProxyFactory进行子类化?

3 个答案:

答案 0 :(得分:2)

我有点运气。说实话,我不知道为什么,但我无法重现Krzysztof所描述的问题。我怀疑......也许......它与我的装配是SN的事实有关......这需要我做出额外的改变......但是一旦我做了,我就能够解决代理问题用于SL测试应用程序中的内部类(带有公共接口)。

我必须对Castle.Core来源做出的唯一更改是使字段ModuleScope.moduleBuilderModuleScope.moduleBuilderWithStrongName受保护而不是私有。但同样,这只是必要的,以便我可以在SL中定义一个SN'd动态组件,该模块由Castle.Core中的ModuleScope禁用。所以,现在我有一个自定义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来源,所以我真的很想听听你的想法Krzysztof ...如果这个解决方案不起作用,也许你可以保护这些字段其他测试用例?

答案 1 :(得分:0)

我可能完全不在这里,但您不是在寻找IncludeNonPublicTypes()吗?

From the documentation

  

注册非公开类型

     

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

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

答案 2 :(得分:0)

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