2

I know interfaces cannot define constructors. Here's what I wish I could do:

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);
}

And I could do this if I took out the line that didn't work, and there would just be a runtime error when trying to load (or possibly save, if I put an assert in there) the object if it didn't have the constructor. I'm just wondering if there's any way to require a class to have a particular constructor that can be used with the Activator. Can I use a custom attribute somehow, and require that attribute to be on the class? Or must I rely on runtime checks to load and save data?

I know I could have a parameterless constructor and a Load(ObjectLoader) method but I don't necessarily want to have a parameterless constructor available to abuse for other purposes.

6 Answers 6

1

what about ISerializable?

Sign up to request clarification or add additional context in comments.

1 Comment

This doesn't really answer the question of compile-time safety, and I'm trying to get maximal storage efficiency and speed out of this, since this will be running on handheld devices.
0

In brief I suggest you use generics as most factories do.

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

However, you seem to have turned it on it head. The class is doing what factory must do. So I do not think it is such a good idea to pass the factory to the entity itself and that is part of the problem you are experiencing in the design.

1 Comment

I'm trying to model this on how ISerializable works, which loads the object by creating a new instance with a parameterless constructor, then calls a method to load the data, passing in the serialization info there. I'm just trying to get it a bit better by not requiring a parameterless constructor.
0

If you are not afraid of using Reflection, like Activator that you have shown, you can do little trick I tend to use:

  1. Make parameterless constructor that is protected
  2. Make Load method, that is also protected (or private, I tend to use virtual protected so I support inheritance)
  3. Create new object using this non-public constructor (through reflection - you can't create instance of your class "just like that" using new operator)
  4. Invoke load method (also using reflection - no one will call it later).

I don't know if this will work for you, but I used that method when I needed to deserialize pretty big game state and it was pretty fast, eventhough all this reflection (for many reasons I did not wanted to use built-in serialization methods and Factory Pattern wouldn't do, so I tend to treat this method as something that may be useful if other methods fail, on the other hand, if I could - I would probably use built-in serialization for simplicity).

1 Comment

I'm more looking for compile-time safety than a different solution from what I already have.
0

How about adding a property on your interface:

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

Then in your factory:

T LoadObject<T>() where T : SavableObject  
{
    var result = (T)Activator.CreateInstance(typeof(T));
    result.ObjectLoader = this;
    return result;
}

Comments

0

Based on your question and comments.

I think you should do it at runtime using reflection.

Combining constructors and interfaces is ilogical from its core. Interface is about what concrete instance can do, not how to initialize it. This can only be achived using abstract class.

Maybe using factory to create instance of the class?

Also I don't think you can get better speed than default ISerializable implementation. Unless you are .NET GURU and have years of time for it.

1 Comment

Except ISerializable uses all kinds of reflection to determine how to do its work, and is not very efficient in the amount of space it takes to save something (and it can't be, because it can't assume anything about the structure), which is a big problem for me that I can overcome, because the application does know the structure.
0

Short answer: It's not possible, I guess. There are no attributes or generalizations I can use to require a specific kind of constructor on a class.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.