Служба WCF, в которой размещен универсальный класс C #, реализующий универсальный интерфейс - PullRequest
3 голосов
/ 03 июня 2011

У меня есть служба WCF, которая предоставляет общий интерфейс (и у службы есть универсальный класс, реализующий этот интерфейс).

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

Теперь я не могу сделать универсальный Main, выполнив Main (string [] args), где T: IComparable , потому что тогда он говорит, Главная точка входа не найдена.

У меня вопрос, как вообще справиться с этим делом?

    // Service Hosting app
    static void Main(string[] args)
    {
       new Thread(new ThreadStart(StartBSTService<T>)).Start();
    }

    static void StartBSTService<T>() where T : IComparable<T>
    {
        string baseAddress = "http://localhost:8080/bst";

        StartAService(typeof(BSTService<T>), baseAddress);
    }

РЕДАКТИРОВАТЬ: Добавление класса обслуживания, а также

  [ServiceContract(Namespace = "http://Microsoft.Samples.GettingStarted")]
  public interface IBSTService<T> where T : IComparable<T> //: ICollection<T>
  {
      [OperationContract]
      void Add(T toAdd);
      // For brevity, not providing all other methods
      // but they are similar IColleciton methods.
  }

public class BSTService<T> : IBSTService<T> where T : IComparable<T>
{
       BinarySearchTree<T> tree = new BinarySearchTree<T>();

       public void Add(T toAdd)
       {
           tree.Add(toAdd);
       }
}

Клиент будет использовать его так же, как вы будете использовать любой универсальный тип:

    BSTService<string> client = new BSTService<string>; 
    // OR
    BSTService<int> client = new BSTService<int>;

EDIT2: Точка @ asawyer кажется логичной, что Main является потребителем универсального класса, поэтому он должен предоставлять тип, но тогда мне нужно начинать новую конечную точку для каждого типа? и как справиться с этим. Как я могу написать служебную оболочку, которая предоставляет только один метод, скажем INIT (Type typeOfBST). клиент вызывает это, чтобы сообщить службе, что он хочет инициировать либо int, либо строку BST. а затем клиент вызывает реальные методы с заданным типом, и сервисные каналы направляют эти вызовы к различным конечным точкам, каждая из которых предоставляет BST с различными типами.

Как вообще обращаться с такими случаями?

Ответы [ 2 ]

5 голосов
/ 03 июня 2011

Когда вы размещаете сервис, вы не можете использовать открытые дженерики.Вы должны указать конкретный тип для размещения конкретного сервиса.Если вы хотите разместить службы для более общих аргументов, вы действительно должны создать новый хост для каждого типа аргумента и предоставить конечную точку с уникальным адресом для каждого из них.Как только служба размещена, она должна иметь возможность сказать, какие типы она принимает и описать их в описании службы (источник для WSDL).

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

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

Редактировать:

Технически, что вы просите, означает: отправить имя типа от клиента к основной службе.Основной сервис проверит, существует ли сервис с таким типом.Если да, он отправит URL сервиса обратно клиенту.Если нет, то он создаст сервис через отражение и запустит его.Он будет хранить информацию о новой размещенной службе и отправляет URL-адрес клиенту.

Другой вариант - запуск всех служб заранее и наличие единой службы маршрутизации WCF, которая будет направлять запрос на исправление службы.

Такие решения выглядят как кошмар обслуживания, и первое будет иметь гораздо худшую производительность, потому что для каждой операции потребуется два сетевых вызова.Кроме того, он обычно не совместим, потому что ваши клиенты должны будут заранее получить общий контракт, чтобы иметь возможность вызывать такие услуги.Просто не делайте этого - определите конечный набор используемых классов и используйте KnownType или DataContractResolver с одним сервисом.

1 голос
/ 03 июня 2011

Когда вы объявляете экземпляр универсального типа, вы должны предоставить параметр не универсального типа, т.е.

interface ITest { }
class Test<T> where T : ITest { }

Вы не можете просто сказать:

var test = new Test<T>();

T неВ этом контексте не много смысла, вам нужен более конкретный тип:

class ImplementsITest : ITest { }

var test = new Test<ImplementsITest>();

В вашем примере вам нужно указать тип при объявлении экземпляра в Main ()

static void Main(string[] args)
{
   new Thread(new ThreadStart(StartBSTService<SomeTypeThatActuallyExists>)).Start();
}

Что BSTService делает с универсальным типом?Это определит, какие типы являются допустимыми параметрами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...