'How to get an instance of a class from ServiceProvider from name of the type
I have to be able to take the name of a class, as a String and use that name to extract from the application's IServiceProvider collection an instance of the appropriate class. The classes that will be created are all injected in to the IServiceCollection at the application start up and have other services injected into their constructors.
If we assume access to a list of types constructed from a variety calls to Assembly.GetExportedTypes(), I can get the Type I need using something like
var type = myListOfServices.FirstOrDefault(_=>_.FullName == "My.Qualified.ClassName");
And I can get an instance of the service using
var instance = serviceProvider.GetService(type);
The problem is that instance is of type object and I have no idea how to cast it to the actual type so that I can access its properties and methods.
UPDATE
The classes I want to create instances of have methods that I need to be able to call and, therefore, I need to be able to cast the object returned by GetService() to the specific type so I can access the methods.
Whilst I have the Type in a variable (see my example above) you cannot use the variable to case the object...
var attempt1 = (type)instance; // won't compile
var attempt2 = instance as type; // won't compile
The point is that the instance I'm trying to get at could be one of any number of classes but all I know about it is the name (this is being supplied as a string message)
The suggestions of How to cast Object to its actual type? aren't appropriate because the answers there assume you know the Type, I'm having to work out what the Type at runtime
Solution 1:[1]
Regardless, if you use DI or whatever, if you only have a string and need to get the corresponding instance, this method can always only return something of type object at compile-time. In that case you have something like this:
public object GetInstanceFromType(string qualifiedClassName)
{
// ... get desired instance from given parameter
}
In a next step it really depends on the desired flexibility. Do all classes that could be returned by this function share a common interface or base class? If yes, you could change the return value of the above method to return that interface or base class and cast the dynamic found instance to that thing and in that case you could call all methods / properties from the specified interface / base class:
public ICommonInterface GetInstanceFromType(string qualifiedClassName)
{
// ...get desired instance from given parameter
return (ICommonInterface)instanceFound;
}
If this doesn't work, you could switch to the strategy pattern. In that case you test of which type your current instance is, cast it to it and then call the desired method:
var instanceFound = GetInstanceFromType("My.Qualified.ClassName");
switch (instanceFound)
{
case SpecificClassOne sco:
sco.DoSomething();
break;
case SpecificClassTwo sct:
sct.DoSomethingElse();
break;
default:
throw new InvalidOperationException($"Type {instanceFound.GetType()} can't be handled.");
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Oliver |
