#c# #wcf
#c# #wcf
Вопрос:
Это такой же дизайн, как и технический вопрос. Я не уверен, что делаю это правильно…
У меня есть WCF API, который взаимодействует с базой данных и передает обратно объект Person (который определен в отдельной .dll), у которого есть как методы, так и атрибуты. Объект отправляется из WCF вызывающему клиенту.
Я хочу вызвать методы пользователя на клиенте. Я понимаю, что они не могут быть отправлены по потоку из API. Однако, если я ссылаюсь на то же самое.dll, которую использует WCF, должен ли я иметь возможность привести API Person к a .Пользователь dll затем запускает методы?
Надеюсь, понятно, чего я пытаюсь достичь.
Ответ №1:
WCF работает через контракты данных. Это модели данных, которые нужно возвращать, например Person
, объект со своими свойствами. Не беспокойтесь о методах во время транспортировки объекта из службы в клиент. Если используется контракт с данными, и вы будете ссылаться на WCF, прокси-класс сгенерирует объект Person .
Если ваша логика более сложная, я полагаю, это зависит от вашей ситуации. Позвольте мне описать в нескольких словах:
-
Если вы не можете изменить источник класса и хотите вызвать открытый метод, лучше использовать отражение. Итак, вы получаете объект из WCF, устанавливаете свойства
Person
объекта с возвращенными значениями, а затем вызываете метод. -
Если вы можете изменить источники класса, вы можете создать базовый интерфейс
IPerson
, реализовать этот интерфейс со свойствами объекта Person в классе и вернутьIPerson
объект. В этом случае вы сможете выполнить приведение.
Подробнее: Хорошо, позвольте мне предоставить вам более подробную информацию:
-
В качестве наилучшей практики я рекомендую создавать отдельные классы с интерфейсами. Это должен быть интерфейс контракта данных, который будет описывать ваш объект. Что-то вроде этого:
[DataContract] public interface IPerson { [DataMember] public int Identifier { get; set; } [DataMember] public string First { get; set; } [DataMember] public string Last { get; set; } public string GetSomething(); }
-
Метод в WCF, который вы реализуете, должен возвращать тип IPerson.
- В общем классе, пожалуйста, реализуйте интерфейс
IPerson
для вашегоPerson
объекта. - Ссылайтесь на эту сборку в своих проектах Service и Client.
- Добавьте веб-ссылку на службу WCF в свой клиентский проект.
- Ваш метод вернет объект типа
IPerson
, поэтому вы можете использовать свой объект Person из общей библиотеки и использовать все его методы.
Комментарии:
1. Спасибо за быстрый ответ, внешняя dll является моей собственной, поэтому я могу изменить исходный код, не могли бы вы подробнее рассказать о варианте 2. Мне нравится концепция, но я не до конца понимаю.
2. Итак, у вас есть dll, содержащая интерфейсы контракта данных, а также разделяемая dll, содержащая реализацию этих интерфейсов? И я должен ссылаться как на DLL-файлы из проекта службы WCF, так и из проекта клиента? Тогда какой смысл в реализации отдельной библиотеки dll интерфейсов?
3. Я получаю жалобу на то, что «[DataContract]» недопустимо для интерфейса
Ответ №2:
WCF поддерживает возможность повторного использования ссылок, которые уже включены в проект. В этом смысле вы можете создать сборку контрактов (сборку, содержащую ваши тонкие модели домена (например Person
, etc), к которым вы можете добавить свою собственную логику.
Затем вы можете добавить сборку как в свою службу WCF, так и в вызывающие клиентские проекты, и дать указание WCF повторно использовать любые существующие ссылки. Таким образом, то, что извлекается из вашей службы, десериализуется в локальную копию a Person
, но не a Person
, которая была бы сгенерирована как прокси, вы фактически получаете полный экземпляр, на котором вы можете выполнять вызовы методов.
Не забывайте, что в этом случае вы выполняете сортировку по значению. Любые изменения, которые вы вносите в Person
экземпляр, являются локальными только для клиента, вам нужно будет снова передать его обратно вверх по течению в вашу службу WCF (через сериализацию), чтобы служба распознала любые изменения и действовала соответствующим образом.
Комментарии:
1. Есть ли лучший способ сделать это? возможно, создать объект Person как на сервере, так и на клиенте? Я думал, что таким образом мне нужно будет создать только один объект Person плюс несколько других, которые могут быть разделены между сервисом и клиентом. Я ищу наиболее элегантное решение, это личный проект, над которым я работаю.
2. Я думаю, вы упускаете суть. Вы реализуете только
Person
один раз. В общей сборке (сборке контрактов). Затем вы ссылаетесь на это в службе и на клиенте.3. Нет, я понимаю, и по состоянию на 15 минут назад у меня есть рабочее решение. Спасибо! Однако, это лучший способ сделать это в общей сборке? Я новичок в WCF. Предвидите ли вы какие-либо проблемы с этим?
4. Ну, это действительно единственный способ, которым вы можете это сделать.
[DataContract]
не поддерживает вызовы методов, поэтому в этом смысле совместное использование сборки между несколькими проектами — неплохая идея.
Ответ №3:
Поскольку вы ссылаетесь на одну и ту же dll, а WCF может быть строго типизированным, вы должны иметь возможность вызывать методы для объекта ответа Person без приведения. При определении класса Person убедитесь, что вы используете атрибут DataContract.
В следующем примере класс Person будет сериализован WCF с тремя элементами данных на стороне сервера. WCF на стороне клиента десериализует ответ … создавая класс Person. Итак, на стороне клиента вы можете вызвать FullName(), и он будет работать без приведения.
[DataContract]
public class Person
{
[DataMember]
public int Identifier { get; set; }
[DataMember]
public string First { get; set; }
[DataMember]
public string Last { get; set; }
public string FullName()
{
return First " " Last;
}
}
Комментарии:
1. Вот как выглядит мой объект, я могу просматривать int, first и last на стороне клиента, но не могу видеть метод… pService. Person p = API. GetPerson(123);
2. Является ли область действия метода общедоступной?