Reputation: 73
I have selveral classes based upon a standard abstract class and they will be loaded from a datatable (for the sample I used an array of int). The class wil be intiated by type and then load the specific details for that class. Currenlty I am doing this with a switch statement but is it possbile to do this an other way?
class Program
{
static void Main(string[] args)
{
var list = new[] {1, 1, 3, 2, 2, 4};
TypeBase typeClass = null;
foreach (var i in list)
{
switch (i)
{
case 1:
{
typeClass = new Type1();
break;
}
case 2:
{
typeClass = new Type2();
break;
}
case 3:
{
typeClass = new Type3();
break;
}
}
}
if (typeClass != null)
{
typeClass.LoadDetails();
}
}
}
public class TypeBase
{
public int Type { get; set; }
public virtual void LoadDetails()
{
throw new NotImplementedException();
}
}
public class Type1 : TypeBase
{
public override void LoadDetails()
{
// Load type Specific details
}
}
public class Type2 : TypeBase
{
public override void LoadDetails()
{
// Load type Specific details
}
}
public class Type3 : TypeBase
{
public override void LoadDetails()
{
// Load type Specific details
}
}
Upvotes: 2
Views: 140
Reputation: 12944
There are several solutions.
1. Create types with reflection
This solution has already been given by Nair. Since I expect your types will not be called Type1
, Type2
, etc. I assume this will not work for you.
2. Store types in a dictionaries with types
Create a dictionary which will replace your switch/case. It contains the types you need to create:
Dictionary<int, Type> types = new Dictionary<int, Type>
{
{1, typeof(Type1)},
{2, typeof(Type2)},
{3, typeof(Type3)}
};
use this to create your types:
Type type;
if (types.TryGetValue(i, out type))
{
TypeBase typeClass = (TypeBase)Activator.CreateInstance(type);
typeClass.LoadDetails();
}
This solution is faster than solution #1, since only one "reflection" operation is used.
3. Store types in a dictionaries with factory methods
Create a dictionary which will replace your switch/case. It will contain factory methods:
Dictionary<int, Func<TypeBase>> factories = new Dictionary<int, Func<TypeBase>>
{
{1, () => new Type1()},
{2, () => new Type2()},
{3, () => new Type3()}
};
use this to create your types:
Func<TypeBase> factory;
if (factories.TryGetValue(i, out factory))
{
TypeBase typeClass = factory();
typeClass.LoadDetails();
}
This solution is faster than solution #2, since there is not reflection used.
4. Store types in a dictionaries with instances
Create a dictionary which will replace your switch/case. It will contain instances of your types. This solution will only work if these instances are immutable and will not change state during calls.
Dictionary<int, TypeBase> typeClasses = new Dictionary<int, TypeBase>
{
{1, new Type1()},
{2, new Type2()},
{3, new Type3()}
};
use this to create your types:
TypeBase typeClass;
if (baseClasses.TryGetValue(i, out baseClass))
{
typeClass.LoadDetails();
}
This solution is faster than solution #3, since no instances are created with every call.
Some side notes
LoadDetails
? In your example member Type
is never used.TypeBase.LoadDetails
an abstract method?keys
are always of type Int32
and are in a continuous range, you could consider using a List<T>
or even an array, which will be faster than a dictionary.Upvotes: 3
Reputation: 5140
Ideally, you should follow factory method to such requirement. Else, if you are happy to follow conventions for your subclass then a cheap trick would be something like below.
using System;
using System.Runtime.Remoting;
namespace ConsoleApplication1
{
internal class Program
{
private static void Main(string[] args)
{
var list = new[] {1, 1, 3, 2, 2, 4};
TypeBase typeClass = null;
foreach (var i in list)
{
ObjectHandle handle = Activator.CreateInstanceFrom("ConsoleApplication1", string.Format("{0}{1}", "Type", i));//Program- Name of the assembl
var typeBase = (TypeBase) handle.Unwrap();
typeBase.Type = i;
typeClass.LoadDetails();
}
}
}
public class TypeBase
{
public int Type { get; set; }
public virtual void LoadDetails()
{
throw new NotImplementedException();
}
}
public class Type1 : TypeBase
{
public override void LoadDetails()
{
// Load type Specific details
}
}
}
Note : I personally won't follow such approach and would more pleased with factory methods or fair number of switches. This is just to flash a possibility only. Please test and amend accordingly (if decide to follow)
Upvotes: 1