2010-11-11 15 views
7

Estoy usando Castle Windsor para SL v2.5.1.0. Lo tengo clases internas de proxy (las interfaces son públicas, por supuesto, pero la implementación es interna, de modo que el consumidor solo conoce la interfaz).Castle Windsor InternalsVisibleTo Silverlight

estoy usando los siguientes atributos en mi montaje con las clases internas

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

En el modo completo .NET 4.0, con los montajes del castillo de .NET 4.0, esto funciona bien y mis tipos se aproxima OK. En Silverlight, con los conjuntos de Castillo de Silverlight, me sale:

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

Además, sólo para solucionar el problema, añadiendo lo siguiente parece hacer ninguna diferencia ...:

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

y no tengo también se verificó en tiempo de ejecución que el nombre del ensamblado hospedado dinámicamente en SL todavía es de hecho DynamicProxyGenAssembly2.

¿Alguna idea? Gracias.

EDITAR:

me encontré con el problema que pienso:

Castillo en .NET 4.0 tiene:

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

} 

en el DefaultProxyBuilder ... y SL 4 tiene

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

Esto es algo que se puede arreglar en la C ¿fuente astle? ¿O debo/debo subclasificar la DefaultProxyFactory?

Respuesta

2

Tuve un poco de suerte con esto. Para ser sincero, no estoy seguro de por qué, pero no pude reproducir el problema descrito por Krzysztof. Sospecho que ... tal vez ... tiene algo que ver con el hecho de que mis ensamblajes son SN ... que me obligaron a hacer un cambio adicional ... pero una vez que lo hice, pude obtener proxies resueltos para clases internas (con interfaces públicas) en una aplicación de prueba SL.

El único cambio que tuve que hacer en la fuente Castle.Core fue proteger los campos ModuleScope.moduleBuilder y ModuleScope.moduleBuilderWithStrongName protegidos en lugar de privados.Pero, de nuevo, eso solo era necesario para poder definir un ensamblado dinámico SN'd en SL, que está desactivado para SL por ModuleScope en Castle.Core. Por lo tanto, ahora tengo una ModuleScope encargo de la siguiente manera:

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

Y un DefaultProxyBuilder personalizado:

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

Y un DefaultProxyFactory personalizado:

/// <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()); 
     } 
    } 

Y la instalación de contenedores:

 container = new WindsorContainer(); 

     container.Kernel.ProxyFactory = new DefaultProxyFactory(); 

No me gusta tanto tener que modificar Castle.Core fuentes, así que realmente me gustaría escuchar tus pensamientos Krzysztof ... tal vez podrías hacer esos campos protegidos si esta solución no funciona para otra prueba ¿casos?

+0

Hmm interesante, así que supongo que la diferencia crítica aquí puede ser que firmes el ensamblaje generado con la misma clave que tus propios ensamblajes, mientras que normalmente si DP genera un ensamblaje con un nombre fuerte, está firmado con la clave de Castle. Así que estoy ** adivinando ** que quizás la regla es que puedes usar el tipo interno del ensamble A en Assebly B si A tiene a B como amigo y ambos están firmados con la misma clave. –

+0

Gracias por investigarlo. Póngalo en el rastreador de problemas y lo analizaremos para vNext. –

+0

¡Gracias por el seguimiento rápido! – Jeff

0

Puedo estar totalmente fuera de lugar aquí, pero ¿no estás buscando IncludeNonPublicTypes()? serán registrados

Registro de tipos no públicos

Por defecto sólo los tipos visibles desde fuera de la asamblea:

From the documentation. Si desea incluir tipos no públicos, hay que empezar con el montaje especificando primero, y luego llamar a IncludeNonPublicTypes

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

No, estoy haciendo mi registro manualmente. El tipo se registra correctamente, es solo en la generación de proxy que explota (debido al código citado anteriormente). – Jeff

+0

Hmmmm. Entonces no tengo idea. Realmente no puedes hacer tus clases públicas: P. –

0

La razón de ello es que el modelo de seguridad de Silverlight no nos permite construir un indicador de un tipo interno, incluso con InternalsVisibleTo.

+0

¿Cómo sugeriría abordar esto desde el punto de vista del diseño? Realmente no quiero que todos los aspectos internos de mi código estén expuestos al consumidor ... solo las interfaces ... Gracias. – Jeff

+0

Nota interesante ... Copié DefaultProxyBuilder de .NET 4.0 en mi código, luego hice mi contenedor Windsor con un ProxyFactory ficticio que instancia el campo del generador con un ProxyGenerator refiriéndome a mi nuevo DefaultProxyBuilder ... y funciona en mi pruebas unitarias! Pero supongo que no funcionará cuando intente ejecutarlo realmente bajo el tiempo de ejecución SL ... – Jeff

+0

Sí, falla en Silverlight en el entorno limitado de seguridad de Silverlight, al menos lo hizo cuando realicé las pruebas. No dude en probarlo, si encuentra una solución, me complace cocinarlo. –

Cuestiones relacionadas