WCF определяет свою собственную версию объекта DataObject в справочнике услуг.
Я создал объект, который я хотел бы передать в вызове WCF... но внутри ServiceReference1... этот объект переопределен... есть ли способ просто использовать исходный объект везде... кажется, что люди сделали это, но я не могу выяснить, что я делаю не так.
Объект используется в качестве параметра функции в контракте на обслуживание.
[OperationContract(IsOneWay = true)]
void UpdateInformation(MyObject myObject);
Ошибка, которую я получаю при попытке вызвать функцию из моего клиента, это "Аргумент 1: невозможно преобразовать из" MyNameSpaceDTO.MyObject "в" MyNameSpace.ServiceReference1.MyObject ""
Объект находится в собственной библиотеке классов DLL и помечен атрибутами [DataObject] и [DataMember].
namespace MyNameSpaceDTO
{
[DataContract]
public class MyObject
{
[DataMember]
public string Name { get; set; }
….
Но также заканчивается в Reference.cs после добавления ссылки на сервис как:
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="MyObject", Namespace="http://schemas.datacontract.org/2004/07/MyNameSpaceDTO")]
[System.SerializableAttribute()]
public partial class MyObject : object, System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged {
[System.NonSerializedAttribute()]
private System.Runtime.Serialization.ExtensionDataObject extensionDataField;
[System.Runtime.Serialization.OptionalFieldAttribute()]
private string NameField;
...
Кроме того, у меня есть следующий набор в разделе "Дополнительно" справочника по добавлению услуг:
[x] Повторное использование типов в ссылочных сборках
(o) Повторное использование типов во всех ссылочных сборках
1 ответ
Для использования службы WCF вы часто видите примеры (и они, несомненно, желательны!), Где вам предлагают добавить эту службу через диалоговое окно " Добавить ссылку на службу ". Путем ссылки на сервис таким образом ваше клиентское приложение создает прокси-классы из WSDL, предоставляемого сервисом.
В результате вы получаете, например, класс MyNameSpaceDTO.MyObject
в вашем контракте-сборка и MyNameSpace.ServiceReference1.MyObject
в вашем клиентском приложении, сгенерированном из WSDL. Это может показаться несколько излишним.
Такое поведение может потребоваться в следующих случаях: представьте, что вы хотите использовать произвольный общедоступный веб-сервис, который вы не контролируете. У вас нет доступа к контрактной сборке, которая определяет типы и т. Д. В этой ситуации создание собственных локальных прокси-классов из предоставляемого WSDL является оптимальным, поскольку это ваш единственный способ получить необходимые типы и так далее.
Но ваша конкретная ситуация кажется немного другой. Я думаю, что вы ищете, это общий контракт. Поскольку вы контролируете клиентский и серверный код (и оба счастливо живете бок о бок в одном и том же решении), вы в удобной ситуации просто поделитесь контрактом:
Таким образом, вместо добавления ссылки на службу в ваше клиентское приложение (с помощью " Добавить ссылку на службу"), вы просто ссылаетесь на сборку контракта (с помощью обычного диалога " Добавить ссылку"). Делая это, будет только один MyNameSpaceDTO.MyObject
так как второй никогда не создается и не нужен. Такой подход называется разделением контрактов.
Пожалуйста, посмотрите на этот пример:
РЕДАКТИРОВАТЬ:
Пожалуйста, обратите внимание на некоторые изменения: наиболее важным является то, что вы обычно не захотите делиться сборкой, которая содержит логику реализации вашего сервиса. Поэтому я извлек эту часть из Контракт-сборки и поместил в отдельную Реализацию-сборку. При этом вы просто делитесь интерфейсами и типами, а не логикой реализации. Это изменение также отражено на скриншоте выше.
Вы можете настроить это маленькое решение с помощью следующих классов:
Контракт - IService1.cs
:
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetData(int value);
}
Реализация - Service1.cs
:
public class Service1 : IService1
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
}
Хост - Program.cs
:
class Program
{
static void Main(string[] args)
{
var baseAddress = new Uri("http://localhost:8732/Design_Time_Addresses/Service1/");
using (var host = new ServiceHost(typeof(Service1), baseAddress))
{
// Enable metadata publishing.
var smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(smb);
// Open the ServiceHost to start listening for messages. Since no endpoints are
// explicitly configured, the runtime will create one endpoint per base address
// for each service contract implemented by the service.
host.Open();
Console.WriteLine("The service is ready at {0}", baseAddress);
Console.WriteLine("Press <Enter> to stop the service.");
Console.ReadLine();
host.Close();
}
}
}
Клиент - Program.cs
:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Press <Enter> to proceed.");
Console.ReadLine();
var binding = new BasicHttpBinding();
var endpoint = new EndpointAddress("http://localhost:8732/Design_Time_Addresses/Service1/");
var channelFactory = new ChannelFactory<IService1>(binding, endpoint);
// Create a channel.
IService1 wcfClient1 = channelFactory.CreateChannel();
string s = wcfClient1.GetData(42);
Console.WriteLine(s);
((IClientChannel)wcfClient1).Close();
Console.WriteLine("Press <Enter> to quit the client.");
Console.ReadLine();
}
}