0

我有一个基于 ServiceStack 3 的客户端-服务器架构。我正在尝试创建一个服务,其请求 DTO 包含一个具有抽象类型的属性,两个不同的具体类实现它。抽象类型可以是抽象类也可以是接口;但是,无论哪种情况,服务器都会在属性中接收一个空对象。

客户端和服务器都引用了三个程序集和相应的命名空间:TestClientServer和。CommonLib

也就是说,分布在三个程序集中:

namespace CommonLib.Services
{
    public class GetThing : IReturn<GetThingResponse> // request DTO
    {
        public IThisOrThat Context { get; set; }
    }

    public class GetThingResponse
    {
        public Dictionary<int, string> Result { get; private set; }

        public GetThingResponse(Dictionary<int, string> result) // response DTO
        {
            Result = result;
        }
    }
}

namespace CommonLib
{
    public interface IThisOrThat { }

    public class This : IThisOrThat { } // and so forth
}

namespace Server.Services
{
    public class GetThing Service : IService
    {
        public object Get(GetThing request)
        {
            var foo = request.Context; // this is null
        }
    }
}

namespace TestClient
{
    class Program
    {
        public const string WSURL = "http://localhost:61435/";

        static void Main(string[] args)
        {
            using (var client = new JsonServiceClient(WSURL))
            {
                var result = client.Get(new GetThing
                                   {
                                       Context = new CommonLib.This("context info")
                                   });
            }
}

如果我将Context属性更改GetThing为 typeThis而不是IThisOrThat,则此方法有效。将其保留为接口,或更改IThisOrThat为抽象类,导致数据以null.

我假设这是一个序列化问题。我尝试将接口更改为抽象类并使用适当KnownType的属性对其进行装饰,但 ServiceStack 的序列化程序似乎并没有从中受益。有什么诀窍可以做到这一点吗?

4

2 回答 2

2

您需要JsConfig.IncludeTypeInfo = true;在客户端启用,因此序列化程序在请求中包含类型信息。这将在类型定义中添加一个额外的属性 ( __type),以便服务知道将其键入为什么。

目前它失败了,因为默认情况下请求不提供类型信息来将对象反序列化为实现接口的类。这是之前提出的一个问题。

问题是当 JSON 客户端发出请求时,它将序列化实现的类,IThisOrThat例如您的This类。但是当它到达另一端时,ServiceStack.Text 不知道要将对象反序列化成什么。类型信息丢失了,所以它不知道IThisOrThat它是什么类型的。因此,如果没有请求中的附加__type信息属性,就会发生这种情况:

设想:

interface ISomething
{
    string Name;
}

class MySomething : ISomething
{
    public string Name { get; set; }
    public int Age { get; set; }
}

class MySomethingElse : ISomething
{
    public string Name { get; set; }
    public int Size { get; set; }
}

然后您使用类型化对象从您的 JsonServiceClient 进行调用

client.Get(new MySomething { Name: "Duck", Age: 20 });

发送的 JSON 将是{ "Name":"Duck", "Age":20 }反序列化器现在选择什么类型?它可能是 aMySomething或 a MySomethingElse,甚至ISomething是它还不知道的另一个。所以因为它不能决定结果是简单的null

通常接口和 DTO 不会混合使用,请参见此处

于 2014-01-31T18:49:42.493 回答
2

我有一个类似的问题,并意识到我没有 { get; 放; 应用于响应 DTO,因此我的对象的结果始终为空...

认为这些信息也可以帮助任何搜索这个的人......

于 2017-04-27T07:54:55.570 回答