I have an interface:
public interface IPath
{
// Some method
}
and I have two classes which are inheriting this interface
public class First : IPath { }
public class Second: IPath { }
By the way, in some method I need to choose which class to use, First or Second, it depending on one string property (type), which I get from database. It looks like:
public void SomeMethod(string type)
{
if (type == "First") { // creating instance of First class }
else if (type == "Second") { // creating instance of Second class }
else { ... }
}
Question is: how can I avoid if/else or switch/case constructions and automaticly create the right instance, depending on the string variable?
2
Answers
You could create a dictionary to map from
string
toType
and the use thatType
andActivator.CreateInstance
to create an instance of that type.Alternatively you could fetch the type using reflection and not need a dictionary at all
(You’d want to extend that code with safety checks, see below)
But this is fundamentally a bad solve. The problem to this is that it’s harder to pass parameters to constructors and it’s unsafe as well, if any of your implementations don’t have a parameterless constructor, this will fail, but not with a compiler error, no it will fail during runtime, i.e once a user (or hopefully testers/ automatic tests) ran into the problem. So a better way would be to store a method that’s invoked to construct the type instead of using
Activator.CreateInstance
, something likeThis solves the problem of parameters for the constructor in that it doesn’t throw a runtime exception.
But we still haven’t solved the problem of actually passing parameters to the constructor, especially when
First
andSecond
require different parameters. The only clean* way to I can think of to handle this in a generic and reusable way is using a Dependency Injection framework/ context to actually construct our instances.But in general, the if/ else if chain or switch statement isn’t necessarily a bad thing, you even see it in some places inside .NET
* You could replicate the part of a DI framework that’s responsible for resolving dependencies for a constructor, but that’s just re-implementing the wheel and might as well save the effort needed and just pull in a dependency like Microsoft.Extensions.DependencyInjection
I have a shorter version as answer, but I saw "MindSwipe" already offered you one: