Question

I Have the following base class :

public abstract class ItemComponentSaver<TType> : where TType : ItemComponent
{
    public abstract bool SaveItem(TType item, object objectRowInTableFromEF, PropertyInfo columnTypeProperty);
}

This one, also has some children, for each of the types that I support. My idea is to use them polymorphically to perform a save operation later on, for example

    public class CellSaver : ItemComponentSaver<Cell>
    {
        public override bool SaveItem(Cell item, object objectRowInTableFromEF, PropertyInfo columnTypeProperty)
        {
                // code here
        }
    }

Now, I know that at some point I need to create this stuff, so there's the unavoidable "switch" like statement, I craeted a factory for this:

public static class ItemComponentSaverFactory
{
    public static ItemComponentSaver<T> GetSaver<T>(ItemComponent entity) where T : ItemComponent
    {
        if (entity is Cell)
            return (ItemComponentSaver<T>)new CellSaver();

        if (entity is Row)
            return (ItemComponentSaver<T>)new RowSaver();
    }

}

The problem is, I can't cast the CellSaver to the return type, because it's generic. I could also return an interface instead of the class tpe, but of course, if I create the interface, I need to make it generic as well, because the return type is like that How can I handle this case in an elegant way??

Was it helpful?

Solution

There are other option for this design,but since we dont know the internals of what you are trying to do my answer will be based only with the presented code. You can rewrite your GetSaver method like this:

     public static ItemComponentSaver<T> GetSaver<T>() where T : ItemComponent
     {
         if (typeof(T) == typeof(Cell))
             return new CellSaver() as ItemComponentSaver<T>;
         else if (typeof(T) == typeof(Row))
             return new RowSaver() as ItemComponentSaver<T>;
         else
             return null;//here you can return what u need in case no types match.
     }

Calling like so...

ItemComponentSaver<Row> saver = ItemComponentSaverFactory.GetSaver<Row>();

OTHER TIPS

I think ItemComponent should have an abstract SaveItem function, and then Cell and Row should implement the SaveItem function.

All ItemComponentSaver<TType> would need to do is call item.SaveItem. No need for individual CellSaver and RowSaver classes at all.

Edit: in fact, unless you do more stuff outside SaveItem, I don't see the need for an ItemComponentSaver<TType> at all. Maybe I'm missing something.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top