2014-01-03 5 views
0

Вопрос в AfterReceiveRequest заключается в том, как узнать пользовательский атрибут, установленный в Операции с помощью OperationDescription? Если есть способ, лучше ли устанавливать пользовательский атрибут в объявлении операции в интерфейсе контракта на обслуживание или в классе реализации службы?Как получить значение Custom Attribute для работы контракта WCF с использованием IDispatchMessageInspector

Для иллюстрации этого вопроса:

public interface IGetterSetterService 
{ 
    [OperationContract, GetterRequest] 
    Data[] GetData(); 
    [OperationContract, SetterRequest] 
    bool SetData(string Data); 
} 

ИЛИ

[WebInvoke(Method = "*", ResponseFormat = WebMessageFormat.Json, UriTemplate = "xyz"] 
[GetterRequest] 
public Data[] GetData() 
{ 
    return new Data[]; 
} 
[WebInvoke(Method = "*", ResponseFormat = WebMessageformat.Json, UriTemplate = "xyz/{data}"] 
[SetterRequest] 
public bool SetData(string data) 
{ 
    return true; 
} 

Теперь IDispatchMessageInspector:

public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) 
{ 
    //Here how to find out the GetterRequest or SetterRequest custom attribute set on an 
    //operation, may be using OperationDescription for the current context? 
} 

ответ

1

Мой полное решение выглядит так, и она работает без каких-либо проблем:
1. Во-первых получить описание операции, как обсуждалось here
2. Затем найти пользовательские атрибуты установить на операции в службе интерфейса:

private UserAction GetIntendedUserAction(OperationDescription opDesc) 
{ 
    Type contractType = opDesc.DeclaringContract.ContractType; 
    var attr = contractType.GetMethod(opDesc.Name).GeCustomAttributes(typeof(RequestedAction), false) as RequestedAction[]; 
    if (attr != null && attr.Length > 0) 
    { 
     return attr[0].ActionName; 
    } 
    else 
    { 
     return UserAction.Unknown; 
    } 
} 
public enum UserAction 
{ 
    Unknown = 0, 
    View = 1, 
    Control = 2, 
    SysAdmin = 3, 
} 
[AttributeUsage(AttributeTargets.Method)] 
public class RequestedAction : Attribute 
{ 
    public UserAction ActionName { get; set; } 
    public RequestedAction(UserAction action) 
    { 
     ActionName = action; 
    } 
} 
0

Я думаю, что вы можете использовать этот код:

public class operationdispatcher : IDispatchMessageInspector 
{ 
    List<Type> MyAttrybutes = new List<Type>() { typeof(behaviorattribute) }; 

    public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel, InstanceContext instanceContext) 
    { 
     var serviceType = instanceContext.Host.Description.ServiceType; 
     var operationName = OperationContext.Current.IncomingMessageHeaders.Action; 
     var methodName = operationName.Substring(operationName.LastIndexOf("/") + 1); 

     var method = serviceType.GetMethods().Where(m => m.Name == methodName && m.IsPublic).SingleOrDefault(); 
     var attributes = method.GetCustomAttributes(true).Where(a => MyAttrybutes.Contains(a.GetType())); 

     foreach (var attribute in attributes) 
     { 
      // you might want to instantiate an attribute and do something 
     } 

     return null; 
    } 
} 

Примечание. Вы используете здесь класс реализации службы, а не интерфейс. Если вы используете метод.GetCustomAttributes (true), тогда вы получите все пользовательские атрибуты по указанному методу (те, которые унаследованы от интерфейса).

+0

Я вижу вашу точку зрения на использование класса обслуживания. Спасибо за ваше решение! Кроме того, я хочу сохранить сборку, в которой интерфейс службы определен (и реализует MessageInspector), отдельно от сборки, которая реализует интерфейс службы, так что службы получают постоянную проверку сообщений как узел хоста службы (который отделен от всех этих) посредством default настраивает указанный инспектор сообщений (программно). Именно по этой причине мое решение находит пользовательские атрибуты из Operations Interface Operations, а не из класса реализации службы. – Vikrant