如何根据类型名称从 ServiceProvider 获取 class 的实例

How to get an instance of a class from ServiceProvider from name of the type

我必须能够将 class 的名称作为 String 并使用该名称从应用程序的 IServiceProvider 集合中提取适当 class。将要创建的 classes 在应用程序启动时全部注入到 IServiceCollection 中,并将其他服务注入到它们的构造函数中。

如果我们假设访问由对 Assembly.GetExportedTypes() 的各种调用构造的类型列表,我可以使用

之类的东西获得我需要的 Type
var type = myListOfServices.FirstOrDefault(_=>_.FullName == "My.Qualified.ClassName");

我可以使用

获取服务实例
var instance = serviceProvider.GetService(type);

问题是 instanceobject 类型,我不知道如何将其转换为 actual 类型以便我可以访问它的属性和方法。

更新 我想创建的 classes 具有我需要能够调用的方法,因此,我需要能够将 GetService() 返回的 object 转换为特定的键入以便我可以访问这些方法。

虽然我在变量中有类型(请参阅上面的示例),但您不能使用该变量来区分对象...

var attempt1 = (type)instance; // won't compile
var attempt2 = instance as type; // won't compile

关键是我试图获取的实例可能是任意数量的 classes 之一,但我所知道的只是名称(这是作为字符串消息提供的)

How to cast Object to its actual type? 的建议不合适,因为那里的答案假设你知道类型,我必须在运行时计算出类型

无论如何,如果你使用 DI 或其他任何东西,如果你只有一个字符串并且需要获取相应的实例,则此方法始终只能 return object 类型的东西 compile-time。在那种情况下,你有这样的东西:

public object GetInstanceFromType(string qualifiedClassName)
{
    // ... get desired instance from given parameter
}

下一步实际上取决于所需的灵活性。所有可以被该函数 return 编辑的 class 是否共享一个公共接口或基础 class?如果是,您可以将上述方法的 return 值更改为 return 该接口或基础 class 并将动态找到的实例转换为那个东西,在这种情况下您可以调用所有方法/ 来自指定接口的属性 / base class:

public ICommonInterface GetInstanceFromType(string qualifiedClassName)
{
    // ...get desired instance from given parameter
    return (ICommonInterface)instanceFound;
}

如果这不起作用,您可以切换到策略模式。在那种情况下,您测试当前实例是哪种类型,将其转换为它,然后调用所需的方法:

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.");
}