2015-07-27 1 views
1

В контексте я создаю класс-оболочку для веб-служб Navision.Реализация универсального приемника List с типом, определяемым внутренним дочерним объектом?

Они имеют следующую структуру:

class JobList_Service : SoapHttpClientProtocol 
{ 
     public Job[] ReadMultiple() 
     { 
      ... 
     } 
} 

я хотел бы сделать что-то вроде следующего:

var jobWS = new NavService<JobList_Service>(); 
jobWS.GetAll<Job>(); 

Я борющегося с обобщениями, я как-то нужно объявить второй тип поскольку он принимает JobList_Service как тип, поэтому возвращает список JobList_Service, чего я не хочу.

Вот моя реализация до сих пор:

public class NavService<T> where T : SoapHttpClientProtocol, new() 
{ 
    private T serviceInstance {get; set;} 

    public NavService() 
    { 
     serviceInstance = new T(); 
     ADSecurity.AuthenticateService_CurrentUser(serviceInstance); 
    } 


    public List<T> GetAll() 
    { 
     try 
     { 
      MethodInfo method = serviceInstance.GetType().GetMethod("ReadMultiple"); 

      ParameterInfo[] paramTypes = method.GetParameters(); //We know that ReadMultiple takes three arguments, we will make that assumption here. 
      var filter = Activator.CreateInstance(paramTypes[0].ParameterType, 0); 
      object[] parameters = { filter, "", new Int32() }; 

      var ret = (List<T>)/*Problem with this cast, obviously*/ method.Invoke(serviceInstance, parameters) ; 
      return ret; 


     } catch (Exception ex) 
     { 

      throw ex; 
     } 
    } 

} 

* EDIT: Если кто-то может предложить лучшее название, не стесняйтесь, я не знаю правильную терминологию.

ответ

1

Вы могли решить эту проблему с двумя параметрами типа - один для типа службы и один для типа реакции:

public class NavService<T, TResponse> 
{ 
    ... 

    public List<TResponse> GetAll() 
    { 

    } 
} 

Но, честно говоря, это выглядит, как ваш шаблонного типа не должны иметь что-то общее с JobList_Service (так как все, что вы делаете с ним, создает экземпляр службы), и что вы должны реализовать интерфейс и использовать это как зависимость от NavService.

Примечание: Я делаю предположение, что у вас есть несколько «сервисов списка», каждый из которых возвращает разные типы. Вы не упомянули об этом в своем вопросе, но это единственная причина, по которой я могу думать о необходимости использования общего метода GetAll.

Start, сделав общий «список услуг» интерфейс, который можно реализовать для различных конкретных типов:

public interface IListService<T> 
{ 
    T[] ReadMultiple(); 
} 

public class JobList_Service : IListService<Job>, SoapHttpClientProtocol 
{ 
    public Job[] ReadMultiple() 
    { 
     ... 
    } 
} 

Тогда передайте это в NavService конструктор:

public class NavService<T> 
{ 
    private IJobListService<T> _serviceInstance; 

    public NavService(IJobListService<T> serviceInstance) 
    { 
     _serviceInstance = serviceInstance; 

     /* authenticate the service outside of this scope (i.e. before 
     * it is passed to this ctor). This breaks encapsulation. 
     * ADSecurity.AuthenticateService_CurrentUser(serviceInstance); */ 
    } 

    public List<T> GetAll() { } 
} 

Это обеспечивает соблюдение более инкапсуляции и также должно помешать вам сделать все это неприятное отражение (вам придется делать некоторые дополнительные работы на этом фронте самостоятельно, так как я не знаю всех деталей конкретных типов) и позволяю вам просто методы вызова.

Edit: Так как Ваш комментарий указывает на то, что ваши услуги генерируются, я бы обернуть каждый из ваших услуг в адаптер, который можно применять интерфейсы:

public class JobListService : IListService<Job> 
{ 
    // Your generated service 
    private readonly JobList_Service _service; 

    ... // set up service in ctor or wherever 

    public Job[] ReadMultiple() 
    { 
     return _service.ReadMultiple(); 
    } 
}   
+0

Хм, но JobList_Service автоматически генерируется кода, не нужно ли добавлять интерфейс к его объявлению каждый раз, когда я его создаю? – David

+0

Что я не понимал - в этом случае вместо прямого применения интерфейса я просто написал небольшие адаптеры, которые отражают сигнатуры метода, но реализуют интерфейс, который возвращается к исходным сервисам. –

+0

Похоже, мне нужно провести некоторое исследование о том, как это сделать, немного новое для дженериков. – David

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