WCF和匿名类型

7
我想在WCF中返回一个匿名类型。这是否可行?

客户端如何知道类型是什么? - Steve Severance
这是一个错误的做法,即使你使用了无类型合同。 - Krzysztof Kozmic
2
以下是为什么有人需要它的几个想法。 1.客户端可能处理JSON响应的JavaScript,无论如何都不知道类型。 2.一个人可能想要能够在不必维护众多响应类型的情况下发出“通用”请求到WCF。 遗憾的是,到目前为止唯一的(积极的)答案(@dave-ward)似乎缺乏实际使这成为可能的配置细节。 - tishma
7个回答

4

您不能使用匿名类型,但也许您在谈论WCF和未经类型化的消息?

在WCF中有一个选项,只需定义一个Message类型的参数(可能还有相同类型的返回值)。这只是发送到WCF的原始消息(并从中返回)。

我找不到太多好的信息 - MSDN上有一些文档,但迄今为止我看到的最好的是Kurt Claeys的博客文章WCF:在WCF操作上未经类型化的消息

我不建议使用这种方法 - 直接处理消息内容需要更多的工作量,而这正是WCF试图使我们免受其困扰的 - 但如果您绝对必须微调消息的每一位 - 这似乎是可行的途径。

Marc


自定义消息可能是解决这个问题的方法。+1 - Randolpho

3

你不能从任何方法中返回匿名类型,对吗?那么为什么你可以从WCF中返回它呢?


我不理解这个负投票 - John 是完全正确的,匿名类型无法从任何 .NET 方法中返回,你只能在当前方法中使用它们。为什么对一个百分之百正确的回答进行负投票呢...... - marc_s
1
不完全是这样。您可以将匿名类型作为“对象”返回,这在Web API和JSON序列化器中完美运行。 - Steve Andrews
这个问题是关于WCF的,而不是Web API。此外,JSON格式包括字段名。它可以很好地被JavaScript序列化和反序列化。但是尝试将字符串值“20”序列化,它会反序列化为字符串还是整数。对于JavaScript来说并不重要,但对于C#来说可能很重要。请注意如何定义“正常工作”。 - John Saunders

1

看起来您无法使用XML序列化器进行操作,因为它会抱怨某个无参构造函数的问题,但是如果您要服务于由Dave Ward指示的ajax客户端,则json序列化器可以正常工作。


1
好的,我明白了。但是如果我为此定义一个类型 - MyObj - 并将其成员标记为 IsRequired=false,那么我如何创建并发送一个只包含其中一些成员的 MyObj 实例呢?这可能吗?
请看 [DataMember(EmitDefaultValue=false)]

0

你绝对可以返回匿名类型。例如:

public object GetLatestPost()
{
  XDocument feedXML = XDocument.Load("http://feeds.encosia.com/Encosia");

  var posts = from feed in feedXML.Descendants("item")
                   select new
                   {
                     Title = feed.Element("title").Value,
                     Link = feed.Element("link").Value,
                     Description = feed.Element("description").Value
                   };

  return posts.First();
}

如果您将该方法作为 ASMX ScriptService 的 WebMethod 进行调用,您将从中获取到这个 JSON:
{"d":
    {"Title":"Using an iPhone with the Visual Studio development server",
     "Link":"http://feeds.encosia.com/~r/Encosia/~3/vQoxmC6lOYk/",
     "Description":" Developing iPhone-optimized portions of an ASP.NET ..."}}

你可以使用返回类型为IEnumerable来返回匿名类型的集合。


有成功的吗?我一直收到504错误而不是响应。 - tishma

0

您可以使用ExpandoObject。当您将DTO中的属性定义为ExpandoObject时,客户端将生成为字典:

合同DTO

public class TaskDTO
{
    public string Type { get; set; }
    public ExpandoObject Args { get; set; }
    public string Id { get; set; }
    public TaskDTO SuccessTask { get; set; }
    public TaskDTO FailTask { get; set; }
    public bool IsFinal { get; set; }
}

客户端

using (var client = new JobServiceClient())
{
    var task = new TaskDTO
    {
        Id = Guid.NewGuid().ToString(),
        Type = "SendEmailTask",
        IsFinal = true
    };
    dynamic args = new ExpandoObject();
    args.To = "who@mail.com";
    args.Title = "test job service";
    args.Content = "test job service";
    task.Args = ((IDictionary<string, object>)args).ToDictionary(i => i.Key, i => i.Value);
    client.Execute(task);
}

服务

dynamic args = dto.Args;

0
不是的。你必须提前定义好你的类型。

好的,我理解了。但是如果我为此定义一个类型 - MyObj - 并将其成员标记为IsRequired=false,那么我如何创建并发送仅包含其中一些成员的MyObj实例?这是否可能? - Tamim Sadikali
请查看Eugene Osovetsky或marc_s的答案。任何一条路线都会有所帮助。我认为marc_s的答案可能是您解决问题的最佳选择。 - Randolpho

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接