通用抽象类继承

时间:2013-11-17 19:24:01

标签: c# generics inheritance

解释

我有一个像这样的抽象类:

public abstract class Serializer<T> where T : new()
{
    T obj { get; set; }

    public string ToXML()
    {
        // return string XML
    }
}

另一个继承此抽象类的类:

public class Account : Serializer<Account>
{
    // Code
    // I don't want to have to implement the methods of 
    // the inherited class/interface.

}

我想像这样访问它:

Account account = new Account();
Console.WriteLine(account.ToXML());

问题:

我是否可以执行此操作并将account传递给属性obj,以便ToXML可以执行将对象转换为字符串的任务?

Serializer s = new Serializer();
s.ToXML(account);

我更愿意让每个对象继承Serialize类及其所有方法,并且只是能够知道除了添加类的继承而不进行任何编辑,我现在可以访问这些方法。< / p>

另一方面,我觉得继承一个类在选择一个接口或一个类之间违反了 is-a can-do 原则,但我不这样做想要覆盖所有的方法,当我已经编写了一般编写的代码时(即,我不想实现接口)。有没有办法像类一样继承接口的方法(没有实现/重写)。

4 个答案:

答案 0 :(得分:2)

尝试返回this

T obj { get { return (T)this; } }

但是,这意味着子类必须将自己作为一个类型参数提供,它是一种奇怪的反复出现的“模板”模式......但是,您可能不一定需要知道对象的类型。编译时将其序列化为XML(如果使用常用的序列化程序),因此在序列化程序方法中访问this就可以了,不需要那个类型参数和该属性。

我个人更喜欢更多hands off approach到抽象基类(使用XmlSerializer):

public interface MXmlSerializable { }
public static class XmlSerializable {
  public static string ToXml(this MXmlSerializable self) {
    if (self == null) throw new ArgumentNullException();
    var serializer = new XmlSerializer(self.GetType());
    using (var writer = new StringWriter()) {
      serializer.Serialize(writer, self);
      return writer.GetStringBuilder().ToString();
    }
  }
}

M代表 mixin 。它实际上是一个带扩展方法的标记接口。像这样使用它:

public class Account : MXmlSerializable { 
  ... 
}

...

Account account = new Account();
...
string accountXml = account.ToXml();

答案 1 :(得分:0)

这样做是怎么回事;

public string ToXML()
    {
        convert `this` to xml directly  
        // return string XML
    }

为什么需要该属性返回对类本身的引用。

使用上述结构,您可以执行以下操作,甚至不需要T属性

Account account = new Account();
Console.WriteLine(account.ToXML());

答案 2 :(得分:0)

你的构造几乎没有意义。 Serializer<T>实例没有明确的观点指向自己。您可以轻松使用this并将其投射到T。此外,除非您的ToXML方法实现了一些非常通用的XML序列化算法(比如通过反射处理当前实例),否则您应该将其设为virtual并将特定实现放在Serializer<T>的祖先中

另外,我还会反对你的继承方法。如果您的Account类实际上是单一目的帐户序列化程序,那么请将其命名为AccountSerializer)。如果没有,并且Account表示实际帐户,则是,从独立读者的角度来看,您混合了两个主要概念:业务对象(Account)和一些技术机制({{1} })。

如果您有通用序列化算法,为什么不在Serializer<T>中接受Serializer<T>个单独的非T类?最终你会更好地分离关注点。

  

有没有办法像类一样继承接口的方法(没有实现/覆盖)。

没有。接口是接口,而不是嵌入特定代码的类。

答案 3 :(得分:0)

如果Abstract类中的代码不会改变只是序列化对象,这种方法没有意义,序列化你不需要知道对象类型(特别是如果你使用xml这意味着构建一个易于访问的字符串)。

如果您希望序列化仅适用于某些对象,请创建一个接口,即

public interface ISerialize
{
}

 public class Account : ISerialize
{
}

然后创建一个Extension方法

public static class ExtenstionMethods
{
     public static string ToXml(this ISerialize obj)
     {
     // code to build xml string
     }
}

这样你可以做你想做的事情,因为Account是Interface的,而ExtensionMethods只能在那个接口上工作,所以你只需要ExtensionMethods类中的代码然后在任何你想要使用的地方包含命名空间“ToXml()”等

Account account = new Account();
Console.WriteLine(account.ToXML());