WCF 在服务参考中定义了它自己的 DataObject 版本
WCF defines it's own version of a DataObject in the Service Reference
我创建了一个对象,我想在 WCF 调用中传递它……但是在 ServiceReference1 中……这个对象被重新定义了……有没有办法在任何地方都使用原始对象……似乎人们已经这样做了但我不知道我做错了什么。
该对象用作服务合同中函数的参数。
[OperationContract(IsOneWay = true)]
void UpdateInformation(MyObject myObject);
当我尝试从客户端调用该函数时出现的错误是“参数 1:无法从‘MyNameSpaceDTO.MyObject’转换为‘MyNameSpace.ServiceReference1.MyObject’”
该对象在它自己的 class 库 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) 在所有引用的程序集中重用类型
对于使用 WCF 服务,您经常会看到示例(毫无疑问,它们是可取的!),其中指示您通过 添加服务引用 对话框添加该服务。通过引用服务,您的客户端应用程序创建代理 classes 形成服务公开的 WSDL。
因此,您最终得到了例如合同程序集中的 class MyNameSpaceDTO.MyObject
和从 WSDL 生成的客户端应用程序中的 MyNameSpace.ServiceReference1.MyObject
。这可能 看起来 有点多余。
您可能需要此行为的一种情况如下:假设您想要使用您无法控制的任意 public Web 服务。您无权访问定义类型等的合同程序集。在这种情况下,从公开的 WSDL 创建您自己的本地代理 classes 是最佳的,因为这是您获取所需类型等的唯一方法。
不过你的具体情况好像有点不一样。我认为您正在寻找的是 共享合同 。由于您控制着客户端 和 服务器代码(并且两者在同一个解决方案中并肩快乐地生活),所以您只需要 分享合约:
因此,无需在您的客户端应用程序中添加服务引用(通过 添加服务引用 ),您只需引用合约程序集(通过通常的 添加参考对话)。通过这样做,只有一个 MyNameSpaceDTO.MyObject
因为第二个永远不会创建也不需要。这种方法称为合同共享。
请看那个例子:
编辑:
请注意一些变化:最重要的一点是您通常不想共享包含服务实现逻辑的程序集。所以我从 Contract-assembly 中提取了该部分并将其放在一个单独的 Implementation-assembly 中。通过这样做,您只需共享接口和类型,而不是实现逻辑。此更改也反映在上面的屏幕截图中。
您可以使用以下 classes 设置该小解决方案:
合同 - 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();
}
}
我创建了一个对象,我想在 WCF 调用中传递它……但是在 ServiceReference1 中……这个对象被重新定义了……有没有办法在任何地方都使用原始对象……似乎人们已经这样做了但我不知道我做错了什么。
该对象用作服务合同中函数的参数。
[OperationContract(IsOneWay = true)]
void UpdateInformation(MyObject myObject);
当我尝试从客户端调用该函数时出现的错误是“参数 1:无法从‘MyNameSpaceDTO.MyObject’转换为‘MyNameSpace.ServiceReference1.MyObject’”
该对象在它自己的 class 库 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) 在所有引用的程序集中重用类型
对于使用 WCF 服务,您经常会看到示例(毫无疑问,它们是可取的!),其中指示您通过 添加服务引用 对话框添加该服务。通过引用服务,您的客户端应用程序创建代理 classes 形成服务公开的 WSDL。
因此,您最终得到了例如合同程序集中的 class MyNameSpaceDTO.MyObject
和从 WSDL 生成的客户端应用程序中的 MyNameSpace.ServiceReference1.MyObject
。这可能 看起来 有点多余。
您可能需要此行为的一种情况如下:假设您想要使用您无法控制的任意 public Web 服务。您无权访问定义类型等的合同程序集。在这种情况下,从公开的 WSDL 创建您自己的本地代理 classes 是最佳的,因为这是您获取所需类型等的唯一方法。
不过你的具体情况好像有点不一样。我认为您正在寻找的是 共享合同 。由于您控制着客户端 和 服务器代码(并且两者在同一个解决方案中并肩快乐地生活),所以您只需要 分享合约:
因此,无需在您的客户端应用程序中添加服务引用(通过 添加服务引用 ),您只需引用合约程序集(通过通常的 添加参考对话)。通过这样做,只有一个 MyNameSpaceDTO.MyObject
因为第二个永远不会创建也不需要。这种方法称为合同共享。
请看那个例子:
编辑:
请注意一些变化:最重要的一点是您通常不想共享包含服务实现逻辑的程序集。所以我从 Contract-assembly 中提取了该部分并将其放在一个单独的 Implementation-assembly 中。通过这样做,您只需共享接口和类型,而不是实现逻辑。此更改也反映在上面的屏幕截图中。
您可以使用以下 classes 设置该小解决方案:
合同 - 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();
}
}