【问题标题】:Is there a way to specify "type of current class" in a C# method signature?有没有办法在 C# 方法签名中指定“当前类的类型”?
【发布时间】:2018-09-26 19:01:46
【问题描述】:

我正在尝试定义一个其他类将扩展的抽象类,它们必须能够将自己序列化为 JSON 并从 JSON 反序列化。我想写这样的抽象类:

public abstract class BaseApiModel {
    public abstract string ToJson();
    public abstract T FromJson(string json);
}

... 其中T 是当前类的类型。然后我会写一个这样的扩展类:

public class ContactApiModel : BaseApiModel {
    public string ContactName { get; set; }
    [...other properties...]

    public override string ToJson() {
        [...return serialized JSON string...]
    }

    public override ContactApiModel FromJson(string json) {
        [...return deserialized object...]
    }
}

当然这不起作用,因为抽象类中的T 没有定义。但是有什么方法可以在 C# 中编写“此方法必须返回当前类的类型”?我只需要让它返回object吗?还是我接近这个错误并且有更好的方法来构建它?

【问题讨论】:

  • 为什么要这样做?您正在将序列化程序/映射硬编码到一个不应该对此一无所知的类中
  • 可以给BaseApiModel添加类型参数。调用它TThis 并在派生类时传递它。例如,C# 没有像 Typescript 这样的多态 this 类型
  • @PanagiotisKanavos 那么您建议将ToJsonFromJson 方法放在哪里?
  • 在实际需要生成JSON的代码中,例如控制器动作。也许甚至不存在——例如,ASP.NET Web API 负责(反)序列化本身。 API DTO 不需要任何特定的处理来进行序列化。如果需要,它们就不是 API DTO。也许您应该寻找将模型映射到 DTO 的方法?
  • @PanagiotisKanavos 这些不仅仅是 DTO 类,它们所做的不仅仅是存储数据。

标签: c# generics design-patterns types


【解决方案1】:

您可以使用泛型声明您的基类,并在您的ContactApiModel 类中将T 参数设置为ContactApiModel,如下所示:

public abstract class BaseApiModel<T> {
    ...
    public abstract T FromJson(string json);
}


public class ContactApiModel : BaseApiModel<ContactApiModel> {
    ...
    public override ContactApiModel FromJson(string json) {
        [...return deserialized object...]
    }
}

【讨论】:

    【解决方案2】:

    对于未来的访问者:

    更聪明的解决方案是在相应的类中根本不实现该方法,而是使用扩展方法:

    public static class ExtendBaseApiModel
    {
        public static string ToJson(this T obj) { /* ... */ }
        public static T FromJson<T>(this T obj, string json) where T : BaseApiModel { /* ... */ }
    }
    

    这将使您的课程保持整洁和整洁,避免序列化混乱。

    还是……有话要说

    如何de-正确序列化

    假设这样做是为了在 ToJson 方法内提供自定义序列化并在 FromJson 方法内提供自定义反序列化,那么您不应该使用自己的怪异方法,而是让框架为您完成。

    对于Json.NET,这应该通过在类上使用JsonConverter 属性并在某处实现相应的JsonConverter 来完成

    趣事

    将扩展方法变体与上面提到的 JsonConverter 相结合,您将能够通过调用 myobjvar.ToJson(...) 来序列化每个对象

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-13
      • 2011-02-13
      • 2010-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-29
      相关资源
      最近更新 更多