views:

77

answers:

3

I need some pretty approach to load polymorhic object

I have base class and several derived classes that base is not aware of. The only thing base class knows is Type enum wich defines which actual class it is.

class Order
{
 OrderType Type;

 bool Load(string filename)
 {
   // load Type
 }
}

class LimitOrder : Order
{

 // some data
 bool Load(string filename)
 {
   // load some data
 }
}

I need to write a Load method for base class Order that would correctly create respective derived class. I am looking for a good pattern.

+1  A: 

Since you have this requirement:

I have base class and several derived classes that base is not aware of. The only thing base class knows is Type enum wich defines which actual class it is.

In order to accomplish this, your derived classes will need to provide some form of registration with the base class. One approach could be to have a static Dictionary<MyTypeEnum,Func<Order>> defined in the base class, and allow subclasses to register themselves with the base class in order to add a specific creation function for their type to the base class dynamically. This way, when the file is parsed, the base class can just call the appropriate function to create the derived type.

Reed Copsey
+2  A: 

The simplest way is to use build-in binary serializer of .Net

 IFormatter formatter = new BinaryFormatter();
 Stream stream = new FileStream(filename, FileMode.Create, FileAccess.Write,     FileShare.None);
 formatter.Serialize(stream, obj);

And put this code in some sort of OrderFactory

class OrderFactory
{
   public static Order Load(string filename) {...}
   public static void Save(string filename, Order order) {...}
}
Alex Reitbort
You can also write out the fully qualified type name and then load the type via reflection using GetType(string fullyQualifiedName). As ever, with these approaches you have to be careful when updating systems already in the field that have historical data.
Quibblesome
Why reinvent something that already exists? And about historical data, you can implement ISerializable and control serialization process any way you want.
Alex Reitbort
This also assumes that the object in the file can be created via serialization, and is not trying to use an already-existing format.
Reed Copsey
Alex Reitbort - who me? Compact Framework doesn't support ISerializable.
Quibblesome
@Quibblesome: well, the question never mentions Compact Framework.
Alex Reitbort
+1  A: 

If you don't want to use the built-in serializers of .NET, you need some kind of factory method. You can place it in a separate factory object, or create a static function in your base class like that:

class Order
{
    public static Order CreateOrder(string filename)
    {
         Stream stream = new FileStream(filename);
         string typeinfo = stream.ReadLine();
         Type t=null;
         if(typeinfo=="LimitOrder")  // this can be improved by using "GetType"
            t=typeof(LimitOrder);
         else if(typeinfo==/* what ever your types are*/
            t= //...
         ConstructorInfo consInfo = t.GetConstructor(new Type[0]);
         Order o= (Order)consInfo.Invoke(new object[0]);
         o.Load(stream);
         stream.Close();
         return o;
    }
}

To get this working, every Order subclass must have a constructor with 0 parameters, and a virtual Load method with a stream parameter. And the first line in your file must be the typeinfo.

Doc Brown