3

Hi have several classes that implement one interface.I want to convert a the items of ILoad list to a its concrete classes like this them I want to call a factory converter to get a another type.

 List<ILoad> list = new List<ILoad>();
    list = GetALlIloads();

    Factory f = new Factory();

     foreach (var item in list)
      {
         var typeOfObject = item.GetType();
         var concreteType = **(typeOfObject)**item;

         var converted = f.ConvertToMeasure(concreteType );
      }

     public class A: Iload
     {
       // something
     } 

     publicclass B: ILoad
     {
       //Something
     }

    public class Factory
    {
     public List<Measure> ConvertToMeausre(A model)
      {
        return some List<Measure>
      }

     public List<Measure> ConvertToMeausre(B model)
      {
        return some List<Measure>
      }
    }
Devsined
  • 3,363
  • 6
  • 30
  • 48
  • 2
    Why? Whats the point of the interface if you are just going to downcast? You wouldn't even know what properties/methods are available. If you did an is/as cast, at least you know the type. – BradleyDotNET Sep 05 '14 at 16:44
  • so is it not working? – Ehsan Sajjad Sep 05 '14 at 16:44
  • 1
    http://en.wikipedia.org/wiki/Polymorphism_(computer_science) – BlackBear Sep 05 '14 at 16:44
  • http://stackoverflow.com/questions/26733/getting-all-types-that-implement-an-interface-with-c-sharp-3-0 -- but why? What are you going to do with them afterwards? – dbc Sep 05 '14 at 16:46
  • All this class are different but from there I can get common properties that I ancapsulate in a specfic object. I have that conversion in a Factory class that have a method ConvertTo and it is overload for each concrete object. I will add that to the post. – Devsined Sep 05 '14 at 17:05
  • I dont want to apply Polymorphism here becuase A and B classes dont have anyrelation with Meausre class and live in a different library. If I do that I will need to include the Measure oobject inside that library and add to each class a convert method that return a List of Meausres – Devsined Sep 05 '14 at 17:19

3 Answers3

4

You can use dynamic type like this

List<ILoad> list = new List<ILoad>();
list = GetALlIloads();

Factory f = new Factory();

foreach (var item in list)
{
    dynamic concreteType = item;
    var converted = f.ConvertToMeasure(concreteType);
}

public class A: Iload
{
  // something
} 

public class B: ILoad
{
   //Something
}

public class Factory
{
    public List<Measure> ConvertToMeausre(A model)
    {
        return some List<Measure>
    }

    public List<Measure> ConvertToMeausre(B model)
    {
        return some List<Measure>
    }
}
BartoszKP
  • 34,786
  • 15
  • 102
  • 130
Grundy
  • 13,356
  • 3
  • 35
  • 55
0

I would just move ConvertToMeasure to your interface.

interface ILoad {
    List<Measure> ConvertToMeasure();
}

class A : ILoad {
    public string PropA { get; set; }


    public List<Measure> ConvertToMeasure()
    {
        throw new NotImplementedException();
    }
}

class B : ILoad {
    public string PropB { get; set; }


    public List<Measure> ConvertToMeasure()
    {
        throw new NotImplementedException();
    }
}

then you can just access the classes normally:

                    List<ILoad> list = new List<ILoad>();

        var s = new A();
        list.Add(new A() { PropA = "test1" });
        list.Add(new B() { PropB = "test2" });
        list.Add(new A() { PropA = "test3" });



        foreach (var item in list)
        {
            item.ConvertToMeasure();
        }

Is this something you could do?

Rgwan
  • 50
  • 5
  • I want to call a factory that recognize the object type. I added more details on the post – Devsined Sep 05 '14 at 17:21
  • I see... Since you're already defining an interface, I think the solution would be to move ConvertToMeasure to your interface. public class A: Iload { // something } publicclass B: ILoad { //Something } – Rgwan Sep 05 '14 at 17:25
0

In your case you can just put all type reflection related code into special function that takes ILoad and processes it further:

public class Factory
{
    public IList<Measure> ConvertToMeasures(ILoad load)
    {
        if (load == null)
            throw new NullArgumentException("load");

        if (load is A)
             return ConvertToMeausre((A)load);

        if (load is B)
             return ConvertToMeausre((B)load);

        throw new NotSupportedException();
    }

    public List<Measure> ConvertToMeausre(A model)
    {
       return some List<Measure>
    }

    public List<Measure> ConvertToMeausre(B model)
    {
        return some List<Measure>
    }
}

and just use it on ILoad in foreach, because converted has no dependency on concrete type of ILoad.

foreach (var item in list)
{
     var converted = f.ConvertToMeasure(item);
}

It is not the best solution, but if you have already downgraded concrete types to interfaces and you can't change them, it is the simplest one.


Of course more OOP-like solution is to modify ILoad interface, but as you have said it is impossible. Nonetheless, if it will greatly simplify the usage scenario you can create your own extended interface and specific wrappers for each ILoad implementer:

public interface ILoadExt: ILoad
{
    IList<Measure> ConvertToMeasure();
}


public class AExt : A, ILoadExt
{
     public List<Measure> ConvertToMeasure()
     {
         return some List<Measure>
     }
}

public class BExt : B, ILoadExt
{
     public List<Measure> ConvertToMeasure()
     {
         return some List<Measure>
     }
}

and wrap items when you get them:

var load = new BExt(factory.GetB());
IList<ILoadExt> loads = new List<ILoadExt>();
loads.Add(load);
Eugene Podskal
  • 10,270
  • 5
  • 31
  • 53
  • I am trying to avoid this solution because I will need to violiate OCP principle every time that i need to add a new class like class D – Devsined Sep 05 '14 at 17:30
  • @Devsined If your logic is type-depended (for A return XX, for B return YY), then the only solution is to either ingrain knowledge of type into the processing functions, or to change the existing types to support this functionality natively. – Eugene Podskal Sep 05 '14 at 17:36