I have an abstract class with a few derived class
public abstract class MyObject
{
public string name { get; set; }
public bool IsObject(string pattern);
...
}
public class MyObjectA : MyObject
{
public string name { get { return "MyObjectA"; } set; }
public bool IsObject(string pattern) { ... }
...
}
public class MyObjectB: MyObject
{
public string name { get { return "MyObjectB"; } set; }
public bool IsObject(string pattern) { ... }
...
}
Now I want to have a function, which returns my the specific class (MyObjectA / MyObectB) based on a string. The problem is, that I have a lot of if/else-clauses to get that:
public MyObject Create(string pattern)
{
MyObjectA obj = new MyObjectA();
if(obj.IsObject(pattern)
{
return obj;
}
else
{
MyObjectB objb = new MyObjectB();
if(objb.IsObject(pattern);
return objb;
else
...
}
}
That looks just awful. What would be a better way to do this?
As Rudi Visser told, you should use reflection.
Also to get your class name you should not hardcode it. If you whant to use your name property just write
if you don't have the name of class, just some string that represent it, than you could check all the classes derived from
MyObject
Yes, use Reflection.
You can use Type.GetType to get an instance of the
Type
for the class by string, then instantiate it usingActivator.CreateInstance
, something like this:You could use
Activator.CreateInstance(string, string)
overload also, but this would not directly return a new instance of theType
required.There are many good answers for your stated question. I would propose however, that you use a factory pattern for this type of requirement.
Your 'factory' could be as simple as adding a static
GetNewMyObject(string pattern)
method to your base class as well as aprotected static Dictionary<string, Type>
. Then your derived classes could simply add their pattern + type to the factory (in a static constructor) allowing new derived classes to be added to the factory without modifying the base class.This way your 'pattern' strings do not have to match the type name and also you do not need to do any logical pattern matching as you can write:
You can use Reflection or System.Activator.CreateInstance to create an instance based on the Type or TypeName as string.
It can be done using Reflection like this...
assemblyName - full path + assembly name
className - fully qualified class name