2010-11-11 159 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