Как реализовать сохранение / загрузку интерфейса с параметризованным конструктором? - PullRequest
2 голосов
/ 04 апреля 2011

Я знаю, что интерфейсы не могут определять конструкторы. Вот что я хотел бы сделать:

public interface SavableObject {
    void Save(ObjectSaver saver);
    SavableObject(ObjectLoader loader); //This, obviously, doesn't work
}


//Loading an object inside ObjectLoader:
T LoadObject<T>() where T : SavableObject  {
    return (T)Activator.CreateInstance(typeof(T), this);
}

И я мог бы сделать это, если бы я вынул строку, которая не работала, и была бы просто ошибка времени выполнения при попытке загрузить (или, возможно, сохранить, если я положил утверждение там) объект, если нет конструктора. Мне просто интересно, есть ли способ требовать, чтобы класс имел определенный конструктор, который можно использовать с Активатором. Могу ли я как-то использовать пользовательский атрибут и требовать, чтобы этот атрибут был в классе? Или я должен полагаться на проверки во время выполнения для загрузки и сохранения данных?

Я знаю, что мог бы иметь конструктор без параметров и метод Load(ObjectLoader), но я не обязательно хочу иметь конструктор без параметров, доступный для злоупотребления для других целей.

Ответы [ 6 ]

1 голос
/ 04 апреля 2011

как насчет ISerializable ?

0 голосов
/ 18 апреля 2011

Краткий ответ: я думаю, это невозможно. Нет атрибутов или обобщений, которые я мог бы использовать, чтобы требовать определенного класса конструктора для класса.

0 голосов
/ 04 апреля 2011

На основании ваших вопросов и комментариев.

Я думаю, вы должны сделать это во время выполнения, используя отражение.

Объединение конструкторов и интерфейсов нелогично по своей сути. Интерфейс - это то, что может делать конкретный экземпляр, а не то, как его инициализировать. Этого можно достичь только с помощью абстрактного класса.

Может быть, использовать фабрику для создания экземпляра класса?

Также я не думаю, что вы можете получить лучшую скорость, чем стандартная реализация ISerializable. Если вы не являетесь .NET GURU и у вас есть на это годы.

0 голосов
/ 04 апреля 2011

Как насчет добавления свойства в вашем интерфейсе:

public interface SavableObject 
{
    void Save(ObjectSaver saver);
    ObjectLoader ObjectLoader {get; set;}
}

Тогда на вашем заводе:

T LoadObject<T>() where T : SavableObject  
{
    var result = (T)Activator.CreateInstance(typeof(T));
    result.ObjectLoader = this;
    return result;
}
0 голосов
/ 04 апреля 2011

Если вы не боитесь использовать Reflection, как показанный вами Активатор, вы можете сделать небольшую хитрость, которую я склонен использовать:

  1. Сделать конструктор без параметров, который защищен
  2. Метод Make Load, который также является защищенным (или частным, я склонен использовать виртуальный защищенный, поэтому я поддерживаю наследование)
  3. Создание нового объекта с помощью этого непубличного конструктора (через отражение - вы не можете создать экземпляр вашегокласс "просто так" с использованием оператора new)
  4. Вызов метода загрузки (также с использованием отражения - никто не вызовет его позже).

Я не знаю, будет ли это работатьдля вас, но я использовал этот метод, когда мне нужно было десериализовать довольно большое игровое состояние, и это было довольно быстро, даже несмотря на все это отражение (по многим причинам я не хотел использовать встроенные методы сериализации, и Factory Pattern не будет делать,поэтому я склонен относиться к этому методу как к чему-то, что может оказаться полезным в случае сбоя других методов, с другой стороны, если бы я мог - я бы, вероятно, использовал buildt-in сериализация для простоты).

0 голосов
/ 04 апреля 2011

Короче говоря, я предлагаю вам использовать generics, как это делает большинство фабрик.

public interface SavableObject<T> : where T : new
{
    void Save(IObjectSaver<T> saver);
    SavableObject<T> Load(ObjectLoader loader); //This, obviously, doesn't work
}

Однако вы, кажется, перевернули его с ног на голову. Класс делает то, что должна делать фабрика. Так что Я не думаю, что это хорошая идея - передать фабрику самой сущности, и это является частью проблемы, с которой вы сталкиваетесь при проектировании. .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...