views:

369

answers:

4

Hi All, what i want to do is select the appropriate class to instantiate based on parenthesis passed in. Currently what i have are two classes (ClassA and ClassB) and to call these im using 2 methods depending on the parenthesis. What i would like to achieve is to use just one method to instantiate either ClassA or ClassB based on the string parenthesis passed.

I dont really know how i can pass back the class object to use..

My old way was in Method A to call the class to instantiate then i could use it. ClassA myclass = new ClassA();

I did think about using the following but i do not (if im honest) know how i instantiate the object o or use it when it is passed back by MyMethod. object o doesnt appear to give me access to the public string methods in Class A or Class B.

public class ClassA
{
    public ClassA()
    {
     //Do something for Class A
    }
    public string msgA()
    {
     return "Here is msg A";
    }
}

public class ClassB
{
    public ClassB()
    {
     //Do something for Class B
    }
    public string msgB()
    {
     return "Here is msg B";
    }
}

private string MyMethod()
{
    object o = GetClassToInstantiate("ClassA");
    //Use object o 
}

private object GetClassToInstantiate(string parameter)
{
    object temp = null;
    switch (parameter)
    {
     case "ClassA":
      temp = new ClassA();
      break;
    }

    return temp;
}

Any suggestions how i can solve this probably very easy situation.

+8  A: 

What you need is a factory method in a base class:

enum ClassType { ClassA, ClassB }

class ClassBase
{
   public static ClassBase Create(ClassType  classType)
   {
       switch (classType)
       {
           case ClassType.ClassA: return new ClassA();
           case ClassType.ClassB: return new ClassB();
           default: throw new ArgumentOutOfRangeException();
       }
   }
}

class ClassA : ClassBase
{
}

class ClassB : ClassBase
{
}

Check the Wikipedia article on the Factory method pattern for more info.

DrJokepu
Awesome, thanks dude.. I knew it would be a simple solution.
Three cheers for Factory methods again!!
Kev
+2  A: 

You would be better off using a design pattern to do this. Take a look at the Abstract Factory and Factory Method patterns on the Gang of Four website.

Abstract Factory

Factory Method

Lusid
+4  A: 

What you want to do isn't generally considered a very useful operation. When you're done all you know about the result is that it's an object. You don't know about any methods or properties it provides. Since C# doesn't (currently-coming soon in v4) allow late binding you can't really do anything with the result.

It becomes much more interesting when class A and class B implement a common interface or are inherited from a common base class. In that case, you could have a generic method that instantiates your real class but returns it as the common interface. This is much more useful, for example with plugin archtitectures.

Joel Coehoorn
4.0 won't provide late binding. There's a subtle difference between late binding and dynamic typing. Late binding binds to a type at runtime. Dynamic typing does not bind at all. This will allow you to modify the type at runtime, which late binding would not.
Michael Meadows
Ok granted, but it will allow you take an object and attempt to call arbitrary methods on it, like the OP was trying to do.
Joel Coehoorn
Yeah, I wasn't trying to disprove your point, but I preach that late binding has nothing beneficial to offer; you still get type mismatches. Late binding only delays these until the user discovers it, instead of during compilation. Dynamic typing allows you to create missing members at runtime!
Michael Meadows
+3  A: 

I would use a common interface for your classes and a seperate factory class with a generic factory method as follows:-

class Program
{
    static void Main(string[] args)
    {
        IAnimal animal = AnimalFactory.CreateAnimal<Dog>();

        animal.Speak();

        Console.ReadKey();
    }
}

public abstract class AnimalFactory
{
    public static IAnimal CreateAnimal<T>() where T : IAnimal, new()
    {
        return new T();
    }
}

public interface IAnimal
{
    void Speak();
}

public class Dog : IAnimal
{
    public void Speak()
    {
        Console.WriteLine("Woof");
    }
}

public class Cat : IAnimal
{
    public void Speak()
    {
        Console.WriteLine("Meow");
    }
}
AdamRalph