-1

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

Stuart Hemming
  • 1,553
  • 2
  • 21
  • 44
  • Do you need to cast it to the actual type because you don't know what methods/properties are available on it, or do you know which methods you can call but the compiler is stopping you? – JohanP Mar 18 '22 at 03:47
  • Do either of these answer your question?: https://stackoverflow.com/questions/18307976/how-to-get-class-type-by-its-class-name -- https://stackoverflow.com/questions/179102/getting-a-system-type-from-types-partial-name – ProgrammingLlama Mar 18 '22 at 03:51
  • Try `dynamic instance = serviceProvider.GetService(type);` – John Wu Mar 18 '22 at 03:58
  • 3
    What problem are you trying to solve? (this feels like an XY Problem) – Jeremy Lakeman Mar 18 '22 at 04:38
  • @JohanP the latter. I have a method that I have to call, but I can't get the compiler to let me – Stuart Hemming Mar 18 '22 at 09:30
  • What your trying to do here is called the [Service locator anti pattern](https://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/) and you should avoid it – Liam Mar 18 '22 at 10:09
  • *I have no idea how to cast it to the actual type* you can (not saying you should) [just cast it to whatever type it is? `(MyClass)obj`](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/types/casting-and-type-conversions) – Liam Mar 18 '22 at 10:11
  • Does this answer your question? [How to cast Object to its actual type?](https://stackoverflow.com/questions/12234097/how-to-cast-object-to-its-actual-type) – Liam Mar 18 '22 at 10:12
  • @liam, no. as all I have a is a string with the name of the type, and whilst I can get the actual Type in to a variable, you can't use a variable to to cast. – Stuart Hemming Mar 18 '22 at 10:31
  • I've added addition explanation above – Stuart Hemming Mar 18 '22 at 10:37
  • What exactly is `type`? As Jeremy stated, this very much seems to be an [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) – Liam Mar 18 '22 at 10:51
  • I **think** what you want is this [Cast to a type from the type name as a string](https://stackoverflow.com/questions/36067071/cast-to-a-type-from-the-type-name-as-a-string). All of this seems extremely bad practice. I would take a long hard look at what your trying to do and why your trying to do it – Liam Mar 18 '22 at 10:52
  • In fact... even when you turn this string into a Type, then what? You can't really use it because the type is only know at runtime, not compile time. You will then disappear into the reflection worm hole. I suspect what you actually want here is polymorphism and/or generics but there isn't enough detail here to confirm. Like I said, you've told us how you think you should solve this issue, not what the actual issue is – Liam Mar 18 '22 at 10:58
  • If you don't know of which type the class is, how do you know the name of the method (and parameter types) you like to call at compile time? – Oliver Mar 18 '22 at 11:26

1 Answers1

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.");
}
Oliver
  • 43,366
  • 8
  • 94
  • 151