2016-07-12 4 views
1

Я создаю набор служб WCF, и одна из вещей, которые мне всегда нужно сделать, это создать ответное сообщение в конце каждой операции.
В настоящее время у меня есть класс Mapper, который содержит ряд этих методов создания (30+ и подсчет), однако я уверен, что могу сделать то же самое с Generics.Как я могу использовать Generics для очистки этого кода?

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

public ClientResponse CreateClientResponse(Header inboundHeader, ClientData data) 
    { 
     var response = new ClientResponse() { 
      Header = inboundHeader, 
      Data = data 
     }; 

     return response; 
    } 

    public OrderResponse CreateOrderResponse(GenericHeader inboundHeader, List<OrderData> data) 
    { 
     var response = new OrderResponse() { 
      Header = inboundHeader, 
      Data = data 
     }; 

     return response; 
    } 

ClientResponse и OrderResponse в настоящее время не связаны каким-либо образом, но оба выглядят одинаково с уважением методы/свойства и т.д.:

public class ClientResponse 
{ 
    public ClientResponse() 
    { 
     Header = new GenericHeader(); 
     Data = new ClientData(); 
    } 

    [DataMember(IsRequired = true)] 
    public GenericHeader Header { get; set; } 

    [DataMember(IsRequired = true)] 
    public ClientData Data {get; set;} 
} 

Моя первая попытка состояла в том, чтобы ввести IResponse<T>, который имел два свойства, и добавить это к классам ответов:

public interface IResponse<T> 
{ 
    GenericHeader Header { get; set; } 
    T Data { get; set; } 
} 

И затем использовать это в моем Generic методе:

public TOut CreateResponse<TOut, TIn>(GenericHeader inboundHeader, TIn data) where TOut : new() 
{ 
    var response = new TOut(); 
    response.Header = inboundHeader; 
    response.Data = data; 
    return response; 
} 

Так что я могу назвать это как так:

var result = CreateResponse<ClientResponse, ClientData>(new GenericHeader(), new ClientData()); 

Но ... Очевидно, что не будет работать дженерики код, потому что TOut не знает о Header и Data.

Мне кажется, мне нужно использовать интерфейс здесь, но я теряюсь, и я не уверен, как вернуть конкретный класс TOut, если я изменю его на работу с интерфейсом.

Любая помощь с благодарностью получена.

+4

Вам не нужно добавить интерфейс к типу ограничения в родовом методе, то есть что-то вроде 'где Tout: новый(), IResponse ' – stuartd

+0

Хм, звучит неправильно. Разумеется, ответ очень сильно коррелирует с * специальным * сообщением и не зависит от какого-либо конкретного типа. Поэтому просто попросите метод обработчика сообщения вернуть объект ответа. –

+1

Добавьте к своему ограничению интерфейс ... Как «где TOUT: IMyContract, new()» –

ответ

0

Добавить заголовок общий аргумент вашего ответа. Затем вы можете использовать свободный синтаксис компоновщика для симпатии (не включенной здесь).

public interface IResponse<TData,THeader> 
{ 
    THeader Header { get; set; } 
    TData Data { get; set; } 
} 

public TOut CreateResponse<TOut, TIn,THeader>(TIn data) 
    where TOut : IResponse<TIn,THeader>,new(), THeader: new() 
    => new TOut(){ Header = new THeader(), Data = data,}; 

var result = CreateResponse<ClientResponse, ClientData,GenericHeader>(new ClientData()); 
+0

Ха-ха, я собирался протестировать то же самое! – Lukos

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