Альтернатива способности определять статические методы расширения - PullRequest
0 голосов
/ 24 февраля 2010

Я понимаю, что я не могу расширять статические классы в C #, я не действительно понимаю причину, почему, но я понимаю , что это невозможно сделать.

Итак, имея в виду, вот что я хотел достичь:

public static class GenericXmlSerialisationExtender
{
    public static void WriteToXML<T>(this T targetObject, string fileName)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(T));
        using (TextWriter writer = new StreamWriter(fileName, false, Encoding.UTF8))
        {
            serializer.Serialize(writer, targetObject);
        }
    }

    public static T ReadFromXML<T>(string fileName)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(T));
        using (TextReader reader = new StreamReader(fileName, Encoding.UTF8))
        {
            return (T)serializer.Deserialize(reader);
        }
    }
}

т.е. Я хотел определить .WriteToXML для экземпляров (есть довольно много классов config / static data, которые мне нужно использовать, которые просто используют Vanilla XML Serialization), а затем .ReadFromXML для типов.

Так эффективно я мог бы назвать что-то вроде:

MyType typeInstance = MyType.ReadFromXML(path_to_data);

Каким был бы «правильный» способ инкапсулировать это? Однажды я работал с коллегой, который считал, что «повторное использование кода» - это копирование и вставка, и я бы не стал ставить себя в эту скобку!

Ответы [ 2 ]

2 голосов
/ 24 февраля 2010

Вы бы определили это точно так, как вы уже сделали, но чтобы вызвать его, вы бы использовали стандартный статический вызов метода:

MyClass deserializedObject = GenericXmlSerialisationExtender.ReadFromXML<MyClass>(@"c:\filename.xml");

(Возможно, вы захотите дать вашему классу GenericXmlSerialisationExtender более подходящее имя, если вы сделаете это, или переместите его в другой статический класс)


Причина, по которой методы расширения не могут работать со статическими методами, заключается в том, что нет объекта, к которому также можно присоединить метод расширения.

В вашем примере:

public static T ReadFromXML<T>(string fileName)

Нигде в этой строке вы не определили тип, который вы хотели бы расширить. Методы расширения требуют, чтобы первым параметром был объект, с которым вы бы хотели, чтобы метод расширения действовал.

Методы расширения являются просто синтаксическим сахаром, как хороший способ создания статического вспомогательного метода.

в .net 2.0 вы бы написали:

public static class StringHelper
{
    public static String AddFullStop(String data)
    {
        return data + ".";
    }
}

String input = "test";
String output = StringHelper.AddFullStop(input);

.net 3.5 дает вам возможность сделать это:

public static class StringExtensions
{
    public static String AddFullStop(this String data)
    {
        return data + ".";
    }
}

String input = "test";
String output = input.AddFullStop();

Поэтому, если вы хотите сделать что-то за пределами полезных методов расширения, вы просто возвращаетесь к старому шаблону статического вспомогательного метода.

1 голос
/ 24 февраля 2010

Я на самом деле не рекомендую это, но как вариант :

public static T ReadFromXML<T>(this T ignored, string fileName)
{
    XmlSerializer serializer = new XmlSerializer(typeof(T));
    using (TextReader reader = new StreamReader(fileName, Encoding.UTF8))
    {
        return (T)serializer.Deserialize(reader);
    }
}

Позвоните с помощью:

MyType typeInstance = default(MyType).ReadFromXml(path_to_data);

Это довольно ужасно, но это в некоторой степени обходит проблему.

Я подозреваю, что на самом деле просто смиритесь и сделайте:

MyType typeInstance = GenericXmlSerialisationExtender.ReadFromXml<MyType>(...);

Если вы можете дать GenericXmlSerialisationExtender более резкое имя, это не должно быть слишком болезненным.

...