即使使用 KnownType,派生类型的属性也不会在 WCF 客户端中反序列化

发布于 2024-12-06 11:30:11 字数 917 浏览 0 评论 0原文

我有以下类型:

public enum MyEnum
{
    Value1,
    Value2
}

[DataContract]
public class Configuration
{
    [DataMember]
    public MyEnum MyValue { get; set; }
    [DataMember]
    public Credentials CredentialValues { get; set; }
}

[DataContract, KnownType(typeof(CustomCredentials))]
public class Credentials 
{

}

[DataContract]
public class CustomCredentials : Credentials 
{
    [DataMember]
    public string Property1 { get; set; }
    [DataMember]
    public string Property2 { get; set; }
}

在我的服务接口上,我有一个函数返回 Configuration 实例,并将其 CredentialValues 属性设置为完全填充的 实例自定义凭据。我没有收到来自客户端或服务器的错误,但是当数据在服务器上进行属性序列化并由客户端接收时,CustomCredentials 上的属性永远不会有值。为了在客户端上正确反序列化这些属性,我需要在此处更改什么?

作为参考,客户端和服务器之间的连接是通过 NetTcpBinding 使用 DuplexChannelFactory 使用由客户端和服务应用程序共享的数据/服务契约项目(服务是自托管的),因此不存在需要重新生成的服务代理类型。

I have the following types:

public enum MyEnum
{
    Value1,
    Value2
}

[DataContract]
public class Configuration
{
    [DataMember]
    public MyEnum MyValue { get; set; }
    [DataMember]
    public Credentials CredentialValues { get; set; }
}

[DataContract, KnownType(typeof(CustomCredentials))]
public class Credentials 
{

}

[DataContract]
public class CustomCredentials : Credentials 
{
    [DataMember]
    public string Property1 { get; set; }
    [DataMember]
    public string Property2 { get; set; }
}

And on my service interface, I have a function that returns an instance of Configuration with its CredentialValues property set to a fully populated instance of CustomCredentials. I receive no errors from the client or the server, but while the data is being property serialized on the server and received by the client, the properties on CustomCredentials never have a value. What do I need to change here in order to have these properties properly deserialized on the client?

For reference, the connection between client and server is made with a DuplexChannelFactory over a NetTcpBinding using a data/service contract project that is shared by the client and service applications (the service is self-hosted), so there are no service proxy types that could need to be regenerated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

≈。彩虹 2024-12-13 11:30:11

将此代码与您的 DataContracts 一起添加到 Contracts 项目中。

[ServiceContract(Namespace = "http://schemas.platinumray.com/duplex", SessionMode = SessionMode.Required, CallbackContract = typeof(IService1Callback))]
public interface IService1
{
    [OperationContract(IsOneWay = true)]
    void GetData();
}

public interface IService1Callback
{
    [OperationContract(IsOneWay = true)]
    void SetData(Configuration config);
}

创建了服务。

public class Service1 : IService1
{
    public void GetData()
    {
        var x = new Configuration()
        {
            MyValue = MyEnum.Value1,
            CredentialValues = new CustomCredentials { Property1 = "Something", Property2 = "Something else" }
        };
        OperationContext.Current.GetCallbackChannel<IService1Callback>().SetData(x);
    }
}

class Program
{
    static void Main(string[] args)
    {

        using (ServiceHost host = new ServiceHost( typeof(Service1), new Uri[] { new Uri("net.tcp://localhost:6789") }))
        {
            host.AddServiceEndpoint(typeof(IService1), new NetTcpBinding(), "Service1");
            host.Open();
            Console.ReadLine();
            host.Close();
        }
    }
}

创建了客户端。

public class CallbackHandler : IService1Callback
{
    public void SetData(Configuration config)
    {
        Console.WriteLine(config.CredentialValues.GetType().Name);
        Console.WriteLine(((CustomCredentials)config.CredentialValues).Property1);
        Console.WriteLine(((CustomCredentials)config.CredentialValues).Property2);
    }
}

class Program
{
    static void Main(string[] args)
    {
        // Setup the client
        var callbacks = new CallbackHandler();
        var endpoint = new EndpointAddress(new Uri("net.tcp://localhost:6789/Service1"));
        using (var factory = new DuplexChannelFactory<IService1>(callbacks, new NetTcpBinding(), endpoint))
        {
            var client = factory.CreateChannel();
            client.GetData();
            Console.ReadLine();
            factory.Close();
        }
    }
}

按预期输出以下内容:

自定义凭证
某物
其他的东西

因此,这实际上在不修改任何数据契约的情况下起作用...如果我恢复到双向操作并直接返回 Configuration 而不使用回调,结果相同。

还尝试使凭据抽象,但无法复制您的问题。

我错过了什么吗?

Added this code to the Contracts project along with your DataContracts.

[ServiceContract(Namespace = "http://schemas.platinumray.com/duplex", SessionMode = SessionMode.Required, CallbackContract = typeof(IService1Callback))]
public interface IService1
{
    [OperationContract(IsOneWay = true)]
    void GetData();
}

public interface IService1Callback
{
    [OperationContract(IsOneWay = true)]
    void SetData(Configuration config);
}

Created the service.

public class Service1 : IService1
{
    public void GetData()
    {
        var x = new Configuration()
        {
            MyValue = MyEnum.Value1,
            CredentialValues = new CustomCredentials { Property1 = "Something", Property2 = "Something else" }
        };
        OperationContext.Current.GetCallbackChannel<IService1Callback>().SetData(x);
    }
}

class Program
{
    static void Main(string[] args)
    {

        using (ServiceHost host = new ServiceHost( typeof(Service1), new Uri[] { new Uri("net.tcp://localhost:6789") }))
        {
            host.AddServiceEndpoint(typeof(IService1), new NetTcpBinding(), "Service1");
            host.Open();
            Console.ReadLine();
            host.Close();
        }
    }
}

Created the client.

public class CallbackHandler : IService1Callback
{
    public void SetData(Configuration config)
    {
        Console.WriteLine(config.CredentialValues.GetType().Name);
        Console.WriteLine(((CustomCredentials)config.CredentialValues).Property1);
        Console.WriteLine(((CustomCredentials)config.CredentialValues).Property2);
    }
}

class Program
{
    static void Main(string[] args)
    {
        // Setup the client
        var callbacks = new CallbackHandler();
        var endpoint = new EndpointAddress(new Uri("net.tcp://localhost:6789/Service1"));
        using (var factory = new DuplexChannelFactory<IService1>(callbacks, new NetTcpBinding(), endpoint))
        {
            var client = factory.CreateChannel();
            client.GetData();
            Console.ReadLine();
            factory.Close();
        }
    }
}

Outputs the following as expected:

CustomCredentials
Something
Something else

So this actually worked without modifying any of your data contracts... The same results if I revert to a twoway operation and just return Configuration directly without using the callback.

Also tried making Credentials abstract but could not replicate your problem.

Have I missed something?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文