2011-02-14 9 views
5

Estoy creando un CodeAccessSecurityAttribute personalizado para manejar la autorización para mis servicios WCF. Construí clase A como tal:Creación de CodeAccessSecurityAttribute personalizado conduce a la excepción en compilar

public class A : CodeAccessSecurityAttribute 
{ 
    public A() : base(SecurityAction.Demand) 
    { 
     // Constructor Code 
    } 

    public override IPermission CreatePermission() 
    { 
     // Permission Creation Code 
    } 

} 

Y en la compilación produce este error.

Error emitting 'A' attribute -- 'Serialized security custom attribute is 
truncated or incorrectly formed.' 

Después de jugar con él un poco me ocurrió con la siguiente muestra que se compila sin error:

public class B : CodeAccessSecurityAttribute 
{ 
    public B(SecurityAction Action) : base(Action) 
    { 
     // Constructor Code 
    } 

    public override IPermission CreatePermission() 
    { 
     // Permission Creation Code 
    } 

} 

Sé que es debido a que la enumeración SecurityAction no se hace referencia directa a la parte pública de la Clase A, pero lo que no puedo descifrar es cómo hacerlo para poder hacerlo con el método de clase A en lugar de la clase B.

Respuesta

11

No conozco el motivo exacto del requerimiento, pero el MSDN documentation on CodeAccessSecurityAttribute claramente estados

Notes to Inheritors

All permission attributes derived from this class must have only a single constructor that takes a SecurityAction as its only parameter.

modificada: La razón de este requisito es que CodeAccessSecurityAttribute es decir, desde un punto de vista de bajo nivel, bastante diferente de otros atributos personalizados. En general, los atributos personalizados se almacenan en los metadatos compilados en la tabla CustomAttribute. Pero los atributos de seguridad, derivados de SecurityAttribute, se almacenan por separado en la tabla DeclSecurity. Y esta tabla no contiene los datos generales como la tabla CustomAttribute, esta tabla contiene el valor de Action, el nombre del tipo de atributo, más un conjunto de propiedades (argumentos con nombre) como en el caso de atributo personalizado. Por lo tanto, el compilador necesita convertir una sintaxis general de atributo personalizado a una entrada en esta tabla de metadatos, por lo que necesita que siga la forma fija indicada anteriormente. (Ver también this blog post, o una partición II, sección 22.11 DeclSecurity:. 0x0E de la Infraestructura Lenguaje Común (CLI) estándar)

+0

I a marcar esto como la respuesta por ahora, pero lo que no entiendo es que si yo estoy forzando la SecurityAction ser un valor al llamar de nuevo a la clase base, ¿por qué importa sobre la clase instanciar? – thaBadDawg

+0

@thaBadDawg: La cosa es que podrías intentar agregar el parámetro requerido al constructor, pero ignorándolo y pasando una constante a 'base()'. Sin embargo, parece que no funciona, de todos modos, los atributos CAS no se evalúan al estilo "clásico", parece. – Mormegil

+0

Siempre usaré "Demand". Es molesto que tenga que especificarlo. Oh, bueno, al menos es una enumeración. – helios456

3

Si proporciona el constructor con un valor por defecto que no tienen que especificar que en el atributo.

public class B : CodeAccessSecurityAttribute 
{ 
    public B(SecurityAction Action = SecurityAction.Demand) : base(Action) 
    { 
     // Constructor Code 
    } 

    public override IPermission CreatePermission() 
    { 
     // Permission Creation Code 
    } 
} 
Cuestiones relacionadas