2013-06-13 3 views
2

Я пытаюсь написать код службы пользовательских авторизации, где я зарегистрировать модуль для проверки разрешений для конкретного перечисления, представляющего доступные виды деятельности:Общий метод и недопустимый контекст исключение

public interface IAuthorizationService 
{ 
    void Register<T>(IAuthorizationModule module); 
    bool Authorize<T>(T activity); 
} 

public class AuthorizationService : IAuthorizationService 
{ 
    private readonly Dictionary<Type, IAuthorizationModule> activities; 

    public AuthorizationService() 
    { 
     activities = new Dictionary<Type, IAuthorizationModule>(); 
    } 

    public void Register<T>(IAuthorizationModule module) 
    { 
     activities[typeof(T)] = module; 
    } 

    public bool Authorize<T>(T activity) 
    { 
     return activities[typeof(T)].Authorize(activity); 
    } 
} 
public interface IAuthorizationModule 
{ 
    bool Authorize<T>(T activity); 
} 

public class OrderAuthModule : IAuthorizationModule 
{ 
    public bool Authorize<OrderActivity>(OrderActivity activity) 
    { 
     return activity == OrderActivity.Cancel; 
    } 
} 

public enum OrderActivity 
{ 
    Place, 
    Cancel, 
    Refund 
} 

Этого код не удается скомпилировать с следующее исключение:

'OrderActivity' is a 'type parameter', which is not valid in the given context

на линии: return activity == OrderActivity.Cancel;.

Я не могу объявить интерфейс как IAuthorizationModule<T>, потому что мне нужен словарь <Type, IAuthorizationModule> для регистрации модулей, которые будут отвечать на тип T (enum).

Что мне здесь не хватает?

+0

В какую строку вы видите эту ошибку? –

+0

Ops, извините. Отредактировано с ошибкой строки. –

+0

Можете ли вы установить ограничение в свой интерфейс luiz? of orderactivity – terrybozzio

ответ

2

Ну, ваш дизайн мне не звучит. Из вашего конкретного класса и реализации AuthorizeService я предполагаю, что каждый IAuthorizationModule должен отвечать только за один вид деятельности. Если я прав, поэтому интерфейс должен быть объявлен как

public interface IAuthorizationModule<T> 
{ 
    bool Authorize(T activity); 
} 

public class OrderAuthModule : IAuthorizationModule<OrderActivity> 
{ 
    public bool Authorize<OrderActivity>(OrderActivity activity) 
    { 
     return activity == OrderActivity.Cancel; 
    } 
} 

Кроме того, необходимо изменить AuthorizationService соответственно:

public class AuthorizationService : IAuthorizationService 
{ 
    private readonly Dictionary<Type, object> activities; 

    public AuthorizationService() 
    { 
     activities = new Dictionary<Type, object>(); 
    } 

    public void Register<T>(IAuthorizationModule<T> module) 
    { 
     activities[typeof(T)] = module; 
    } 

    public bool Authorize<T>(T activity) 
    { 
     return ((IAuthorizationModule<T>)activities[typeof(T)]).Authorize(activity); 
    } 
} 

Таким образом, это проще реализовать каждый IAuthorizationModule.

+0

Вы правы, каждый 'IAuthorizationModule' несет ответственность только за одно действие (перечисление). Мне понравилось ваше решение, где мне нужно делать литье типов только в одном месте ('AuthorizationService') вместо каждого' IAuthorizationModule'. Только одна коррекция: подпись метода в 'IAuthorizationModule ' должна быть 'bool Authorize (T activity)'. Использование 'Authorize ' дает мне ту же ошибку, что и у меня ... Большое спасибо. –

1

Пожалуйста попробовать это Луиз

EDIT:

public bool Authorize<T>(T activity) 
     { 
      return activity.Equals(OrderActivity.Cancel); 
     } 

EDIT: сделать переключатель заявление попробовать это LuiZ

OrderActivity act = (OrderActivity)Enum.Parse(typeof(OrderActivity), activity.ToString()); 
      switch (act) 
      { 
       case OrderActivity.Place: 
        return true; 
        break; 
       case OrderActivity.Cancel: 
        return false; 
        break; 
       default: 
        return default(bool); 
      } 

Важным является линия над переключателем(), там вы анализируете переменную активности в переменной перечисления и помещаете ее в коммутатор, надеемся, что это поможет ...... 1) мы, где проверяем равенство на T (placeholder не установлен на nything в моем случае) и значение перечисления, в вашем случае это было исключение (с использованием типа (T)) 2) он не работал, потому что мы имеем дело с T, которое не определяется как что-то конкретное, а swtch работает на bool, string , char, int, enum или соответствующий тип NULL и активность в моем редактировании были T, рад, что я мог помочь :)

+0

Я ответил на ваш [комментарий] (http://stackoverflow.com/questions/17099035/generic-method-and-invalid-context-exception/17099397?noredirect=1 # comment24736483_17099035), заявив, что перед редактированием я буду использовать только значения перечисления. На самом деле у меня будет больше модулей и перечислений (например, «CustomerAuthModule» и «CustomerActivity»), отсюда и необходимость в общем решении. Извините за путаницу. –

+0

, то этот метод авторизации будет использоваться в этом классе (OrderAuthModule), получающем различные перечисления, или будет реализован 1 метод (Авторизовать) в разных классах? ... например, этот класс получает этот метод, получающий orderactivity, другой класс получает этот метод но получая другие перечисления? – terrybozzio

+0

только что отредактировал luiz, протестировал его и получил правильные ответы, надеюсь, что вы будете такими же ... – terrybozzio

2

Обновление Authorize для <T> мог это исправить ..

public class OrderAuthModule : IAuthorizationModule 
{ 
    public bool Authorize<T>(T activity) 
    { 
     return activity.ToString() == OrderActivity.Cancel.ToString(); 
    } 
} 

Использование:

 var authorization = new AuthorizationService(); 

     var orderMod = new OrderAuthModule(); 

     authorization.Register<OrderActivity>(orderMod); 

     var status = authorization.Authorize(OrderActivity.Place); 

Надежда, я не получил контекст неправильно ...

Для записей:

Вы можете ограничить общий параметр типа, чтобы быть тип значения (например, Int, логическое значение, и перечисления) или любой пользовательской структуры с использованием структуры ограничение: Ref

public class MyClass<T> where T : struct 

{...} 
+0

Ваш ответ верный, но я выбрал ответ @ tia как принятый, потому что литье типов происходит только в одном месте ('AuthorizationService') вместо каждого' IAuthorizationModule'. Большое спасибо за Вашу помощь. :) –

+0

@LuizDamim: Согласен! :) –

Смежные вопросы