2010-11-11 91 views
7

我正在使用Castle Windsor for SL v2.5.1.0。我有它的代理内部类(当然,接口是公共的,但实现是内部的,所以消费者只知道接口)。Castle Windsor InternalsVisibleTo Silverlight

我用下面的属性在我的组装与内部类

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

在完整的.NET 4.0模式,与.NET 4.0城堡组件,这工作得很好,我的类型代理确定。在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。

任何想法?谢谢。

编辑

我发现我想这个问题:

城堡的.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); 
} 

这是可以固定在C ast源?或者我需要/应该为DefaultProxyFactory子类?

回答

2

我对此有一些好运。说实话,我不知道为什么,但我不能再现克尔兹索夫所描述的问题。我怀疑......也许......这与我的程序集被SN'd这个事实有关......这需要我作出额外的改变......但是一旦我做了,我就能够得到代理程序了用于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 ...也许你可以让这些字段保护,如果这种解决方案不适用于其他测试案件?

+0

嗯有趣的 - 所以我想这里的关键区别可能是你签署生成的程序集与你自己的程序集相同的密钥,而通常如果DP生成强命名的程序集它使用城堡的密钥签名。所以我** **猜测**或许规则是,如果A具有B作为朋友并且两者都使用相同的密钥签名,则可以使用组装A中的内部类型。 – 2010-11-17 02:45:42

+0

感谢您的调查 - 将其放置在问题跟踪器中,我们将考虑将其烧入vNext中。 – 2010-11-17 02:46:19

+0

感谢您的快速跟进! – Jeff 2010-11-17 02:54:53

0

我可能完全脱离了这里的基地,但是您不是在寻找IncludeNonPublicTypes()

From the documentation

注册的非公共类型

默认情况下,只能从组件外部可见的类型将被注册。如果你想包括非公共类型,你有先指定装配开始,然后调用IncludeNonPublicTypes

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

不,我正在手动进行注册。该类型的注册状态良好,它只是在代理生成中爆发(因为上面引用的代码)。 – Jeff 2010-11-11 18:11:14

+0

嗯。然后我不知道。你真的无法公开你的课程:P。 – 2010-11-11 18:56:08

0

其原因是,Silverlight的安全模型不允许我们构建一个代理一个内部类型,即使有InternalsVisibleTo。

+0

那么你会如何建议从设计的角度来解决这个问题呢?我真的不希望我的代码的所有内部暴露给消费者......只有接口......谢谢。 – Jeff 2010-11-11 22:58:46

+0

有趣的一面...我没有将.NET 4.0中的DefaultProxyBuilder复制到我的代码中,然后用一个虚拟的ProxyFactory制作了我的Windsor容器,它使用ProxyGenerator实例化了生成器字段,并引用了我的新DefaultProxyBuilder ...并且它在我的单元测试!但我猜想在我尝试在SL运行时下运行它时会失效...... – Jeff 2010-11-11 23:00:33

+0

是的,它在Silverlight安全沙箱中的Silverlight上失败,至少在我运行测试时它失败了。随时尝试一下,如果你找到一个解决方案,我很乐意将它烘烤。 – 2010-11-12 03:25:28