2016-04-05 9 views
0

я пользовательский атрибут применяется к Crud методов хранилища для управления доступом:CodeAccessSecurityAttribute производный класс метание System.TypeLoadException (Сбой произошел при загрузке типа)

Public Class SecureDbContextGenericRepository(Of TEntity As Class, TContext As DbContext) 
    Inherits DbContextGenericRepository(Of TEntity, TContext) 
    Public Sub New(connectionService As IConnectionService) 
    MyBase.New(connectionService) 
    End Sub 
    <EmployeeRoleRequirement(SecurityAction.Demand, EmployeeRoles:=EmployeeRoles.DataWriter)> 
    Public Overrides Sub Delete(ParamArray entities() As TEntity) 
    MyBase.Delete(entities) 
    End Sub 
    <EmployeeRoleRequirement(SecurityAction.Demand, EmployeeRoles:=EmployeeRoles.DataWriter)> 
    Public Overrides Sub Insert(ParamArray entities() As TEntity) 
    MyBase.Insert(entities) 
    End Sub 
    <EmployeeRoleRequirement(SecurityAction.Demand, EmployeeRoles:=EmployeeRoles.DataReader)> 
    Public Overrides Function [Select](Optional predicate As Func(Of TEntity, Boolean) = Nothing) As IList(Of TEntity) 
    Return MyBase.Select(predicate) 
    End Function 
    <EmployeeRoleRequirement(SecurityAction.Demand, EmployeeRoles:=EmployeeRoles.DataWriter)> 
    Public Overrides Sub Update(ParamArray entities() As TEntity) 
    MyBase.Update(entities) 
    End Sub 
End Class 

Это реализация атрибута:

Public Class EmployeeRoleRequirementAttribute 
    Inherits CodeAccessSecurityAttribute 
    Public Sub New(action As SecurityAction) 
     MyBase.New(action) 
    End Sub 

    Public Overrides Function CreatePermission() As IPermission 
     Return New EmployeeRolePermission(_EmployeeRoles) 
    End Function 

    Public Property EmployeeRoles As EmployeeRoles 
    End Class 

<Flags> 
    Public Enum EmployeeRoles As Integer 
    DataReader = 0 
    DataWriter = 1 
    End Enum 

И разрешение:

Public Class EmployeeRolePermission 
    Implements IPermission 
    Public Sub New(employeeRoles As EmployeeRoles) 
     _EmployeeRoles = employeeRoles 
    End Sub 

    Public Function Copy() As IPermission Implements IPermission.Copy 
     Return New EmployeeRolePermission(_EmployeeRoles) 
    End Function 
    Public Sub Demand() Implements IPermission.Demand 
     Dim principal = DirectCast(Thread.CurrentPrincipal, ProductionAssistantPrincipal) 
     If Not principal.IsInRole(_EmployeeRoles) Then 
     Throw New SecurityException(String.Format(My.Resources.EmployeeRoleNotFound, 
                principal.Identity.Name, 
                _EmployeeRoles.ToString())) 
     End If 
    End Sub 
    Public Sub FromXml(e As SecurityElement) Implements ISecurityEncodable.FromXml 
     Throw New NotImplementedException() 
    End Sub 
    Public Function Intersect(target As IPermission) As IPermission Implements IPermission.Intersect 
     Return New EmployeeRolePermission(_EmployeeRoles And DirectCast(target, EmployeeRolePermission).EmployeeRoles) 
    End Function 
    Public Function IsSubsetOf(target As IPermission) As Boolean Implements IPermission.IsSubsetOf 
     Return _EmployeeRoles.HasFlag(DirectCast(target, EmployeeRolePermission).EmployeeRoles) 
    End Function 
    Public Function ToXml() As SecurityElement Implements ISecurityEncodable.ToXml 
     Throw New NotImplementedException() 
    End Function 
    Public Function Union(target As IPermission) As IPermission Implements IPermission.Union 
     Return New EmployeeRolePermission(_EmployeeRoles Or DirectCast(target, EmployeeRolePermission).EmployeeRoles) 
    End Function 

    Public ReadOnly Property EmployeeRoles As EmployeeRoles 
    End Class 

Каждый раз, когда один из методы CRUD достигаются, генерируется TypeLoadException. Я действительно не знаю причину этого, но если я удалю атрибуты из методов CRUD, все будет хорошо.

ответ

1

Это похоже на свойство enum-value по атрибуту (см. https://connect.microsoft.com/VisualStudio/feedback/details/596251/custom-cas-attributes-with-an-enum-property-set-cause-a-typeloadexception). Чтобы обойти эту проблему, вы можете использовать свойство атрибута string для атрибута и преобразовать его в перечисление либо в свойстве свойств, либо непосредственно перед созданием разрешения. (Лично я бы предпочел бы первый в интересах включения ранней проверки, но ymmv ...)

+0

команда Визуальная разработка Студия куча реальных дебилов. 6-летняя проблема все еще не исправлена. –

0

Другим обходным путем является свойство атрибута типа, которое используется в Enum, в данном случае Integer.

Public Class EmployeeRoleRequirementAttribute 
    Inherits CodeAccessSecurityAttribute 
    Public Sub New(action As SecurityAction) 
    MyBase.New(action) 
    End Sub 
    Public Overrides Function CreatePermission() As IPermission 
    Return New EmployeeRolePermission(CType(_RequiredEmployeeRoles, EmployeeRoles)) 
    End Function 

    Public Property RequiredEmployeeRoles As Integer 
End Class 

<Flags> 
Public Enum EmployeeRoles As Integer 
    DataReader = 0 
    DataWriter = 1 
End Enum 

Тогда вам не нужно использовать строку, которая не позволяет легко комбинируя флагов, когда используется атрибут:

<EmployeeRoleRequirement(SecurityAction.Demand, RequiredEmployeeRoles:=EmployeeRoles.DataReader Or EmployeeRoles.DataWriter)> 
Sub SecuredMethod() 
End Sub