2013-11-17 6 views
2

Объяснение:Generic абстрактный класс наследования

У меня есть абстрактный класс, например, так:

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 класс и все его методы, и просто быть в состоянии знать, что без редактирования ничего, кроме добавления наследования класса, теперь я могу получить доступ к этим методам.

На другой ноте, я чувствую, что наследующий класс нарушает есть- и может сделать- принципов между выбором интерфейса или классом, но я не хочу, чтобы переопределить все методы, когда я уже имеют код, написанный для его общего в классе (т. е. я не хочу реализовывать интерфейс). Есть ли способ унаследовать методы интерфейса, такие как класс (без реализации/переопределения).

ответ

2

Попытки вернуть this:

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

Но это означает, что класс ребенок должен обеспечить себя в качестве параметра типа, это любопытно повторяющийся «шаблон» шаблон ... Для того, чтобы быть уверенными, хотя, вам необязательно знать тип объекта во время компиляции, чтобы сериализовать его в XML (если вы используете обычные сериализаторы), поэтому доступ к в методе сериализатора был бы в порядке, без необходимости этого параметра типа и этого свойства ,

я лично предпочитаю более 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(); 
0

Как насчет этого;

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

Зачем вам нужно свойство, чтобы вернуть ссылку на сам класс.

С выше структурами вы можете сделать следующее, даже не нуждаясь в T свойства

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

Ваша конструкция вряд ли имеет смысл. Для примера Serializer<T> нет четкой точки, указывающей на себя. Вы можете легко использовать this и бросить его на T. Кроме того, если ваш метод ToXML не реализует какой-то действительно общий алгоритм сериализации XML (например, обработку текущего экземпляра с помощью отражения), вы должны сделать его virtual и разместить конкретные реализации в предках Serializer<T>.

Кроме того, я бы также возражал против вашего подхода к наследованию. Если ваш класс Account на самом деле является единственным целевым счетом serializer, то назовите его так (AccountSerializer). Если нет, и Account представляет собой реальную учетную запись, то да, с точки зрения независимого читателя вы смешиваете две основные концепции: бизнес-объект (Account) и некоторый технический механизм (Serializer<T>).

Если у вас есть универсальный алгоритм сериализации, почему бы вам просто не иметь отдельный, не абстрактный тезис Serializer<T> класс, принимающий T экземпляров в ToXML()? Вы в конечном итоге получите лучшее разделение проблем.

Есть ли способ наследовать методы интерфейса, такие как класс (без реализации/переопределения).

№ Интерфейсы: интерфейсы, а не классы, чем встроенный конкретный код.

0

Если ваш код в абстрактном классе не изменится только для сериализации объекта, этот подход не имеет смысла. Сериализация Вам не нужно знать тип объекта (особенно если вы используете xml, что означает создание строка доступа).

Если вы хотите Сериализации доступна только для определенных объектов сделать интерфейс т.е.

public interface ISerialize 
{ 
} 

public class Account : ISerialize 
{ 
} 

, а затем создать метод расширения

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

Таким образом, вы можете делать то, что вы хотите сделать, потому что счета является интерфейсом, а ExtensionMethods будут работать только на этом интерфейсе, поэтому вам нужен только код в классе ExtensionMethods, а затем включать пространство имен, где вы хотите использовать «ToXml()» и т. д.

Account account = new Account(); 
Console.WriteLine(account.ToXML()); 
Смежные вопросы