C# 按名称获取类的实例

C# 按名称获取类的实例,c#,asp.net-core-5.0,C#,Asp.net Core 5.0,我在appsettings.json中设置了StrategyName,它表示策略类的名称。我需要一个实例 ITradingStrategy\u tradingStrategy=StrategyUtils.GetStrategyInstancelogger,\u tradeOptions.StrategyName 这等于 ITradingStrategy _tradingStrategy=新的RSistategyLogger; 是否有可能以更好的方式制作?它能工作,但看起来很难看。由于我们从app

我在appsettings.json中设置了StrategyName,它表示策略类的名称。我需要一个实例


ITradingStrategy\u tradingStrategy=StrategyUtils.GetStrategyInstancelogger,\u tradeOptions.StrategyName 这等于

ITradingStrategy _tradingStrategy=新的RSistategyLogger; 是否有可能以更好的方式制作?它能工作,但看起来很难看。由于我们从appsettings.json开始就知道了策略名称,因此应该有一种更好的ASP.NET核心方式来获得它。也许是一些很酷的扩展方法,我不知道

appsettings.json 密码 公共类LiveTradeManager:ITradeManager { 专用只读ILogger\u记录器; 专用只读IExchangeClient\u exchangeClient; 私有只读ITradingStrategy(交易策略); 私有只读交换选项\u交换选项; 私有只读交易选项_TradeOptions; 公共LiveTradeManagerLogger记录器,IConfiguration配置,IExchangeClient交换客户端 { _记录器=记录器; _exchangeClient=exchangeClient; _exchangeOptions=configuration.GetSectionExchangeConfiguration.Get; _tradeOptions=configuration.GetSectionTradeConfiguration.Get;
_tradingStrategy=StrategyUtils.GetStrategyInstancelogger,\u tradeOptions.StrategyName;//这是一行 } } 公共静态ITradingStrategy GetStrategyInstanceLogger记录器,字符串strategyName { var strategyType=Assembly.GetAssemblytypeofStrategyBase .GetTypes.FirstOrDefaulttype=>type.IsSubclassOftypeofStrategyBase&&type.Name.EqualStrategyName; 如果strategyType==null { 抛出新ArgumentException$找不到策略\{strategyName}\,nameofstrategyName; } var strategy=Activator.CreateInstancestrategyType,记录器为ITradingStrategy; 回报策略; } //策略 公共接口ITradingStrategy { IReadOnlyList准备ReadOnlyList蜡烛; } 公共抽象类策略库:ITradingStrategy { 专用只读ILogger\u记录器; 受保护的策略baseilogger记录器 { _记录器=记录器; } 公共摘要IReadOnlyList PrepareReadOnlylist蜡烛; } 公共类战略:战略基础 { 专用只读ILogger\u记录器; 公共RSistategyLogger记录器:baselogger { _记录器=记录器; } 公共覆盖IReadOnlyList PrepareReadOnlyList蜡烛 { 信息测试; } } //主要 公共课程 { 公共静态无效字符串[]args { CreateHostBuilderargs.Build.Run; } 公共静态IHostBuilder CreateHostBuilderstring[]args=> Host.CreateDefaultBuilderargs .ConfigureAppConfigurationhostingContext,配置=> { 配置 .AddJsonFileappsettings.json .添加环境变量; } .ConfigureServiceshostingContext,服务=> { 服务.AddSingleton Logger.Logger=新的LoggerConfiguration .ReadFrom.ConfigurationhostingContext.Configuration .CreateLogger; services.AddSingleton; services.AddSingleton; services.AddHostedService; } .useserlog; }
您的问题可以通过多种方式解决,使用反射将是最后一种方式

从您的问题陈述中,我认为您有多个实现ITradingStrategy接口的策略分类,并且您可以使用appsettings.json文件中的配置值来决定使用哪种策略

这里可以使用的方法之一是使用factory根据配置值初始化适当的策略类

下面是工厂类和接口,它将根据传递给它的策略名称创建策略类对象

public interface IStrategyFactory
{
    ITradingStrategy GetStrategy(string strategyName);
}

public class StrategyFactory : IStrategyFactory
{
    private IServiceProvider _serviceProvider;
    public StrategyFactory(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;

    }
    public ITradingStrategy GetStrategy(string strategyName)
    {
        switch (strategyName)
        {
            case "Rsi":
                // Resolve RsiStrategy object from the serviceProvider.
                return _serviceProvider.GetService<RsiStrategy>();
            case "Dmi":
                // Resolve DmiStrategy object from the serviceProvider.
                return _serviceProvider.GetService<DmiStrategy>();
            default:
                return null;
        }
    }
}
要使上述代码正常工作,您需要将分类在serviceCollection中的策略注册

services.AddSingleton<RsiStrategy>();
services.AddSingleton<DmiStrategy>();
使用上述代码,从StrategyBase继承的所有类型都在serviceCollection中注册。现在使用serivceProvider,我们可以获得所有注册的实例,并查找具有正确strategyName的实例

因此,工厂的GetStrategy方法如下所示

//Get all the types which are inheriting from StrategyBase class from the assembly.
var strategyTypes = Assembly.GetAssembly(typeof(StrategyBase))
    ?.GetTypes()
    .Where(type => type.IsSubclassOf(typeof(StrategyBase)));

if (strategyTypes != null)
{
    //Loop thru the types collection and register them in serviceCollection.
    foreach (var type in strategyTypes)
    {
        services.Add(new ServiceDescriptor(typeof(StrategyBase), type, ServiceLifetime.Singleton));
    }
}
public ITradingStrategy GetStrategy(string strategyName)
{
    var strategies = _serviceProvider.GetServices<StrategyBase>();

    var strategy = strategies.FirstOrDefault(s => s.GetType().Name == strategyName);

    if (strategy == null)
    {
        throw new ArgumentException($"The strategy \"{strategyName}\" could not be found.", nameof(strategyName));
    }

    return strategy;
}

我希望这将帮助您解决您的问题。

StrategyUtils.GetStrategyInstance应该使用ServiceCollection从DI解析类型。@ChetanRanpariya,我如何通过appsettings.json中的策略名称来解析?@ChetanRanpariya,请记住,我还想检查它是否是StrategyBase的子类类型。是否有其他类正在实现ITradingStrategy接口,但没有从StrategyBase类继承?将来还会有其他类实现ITradingStrategy接口吗?@ChetanRanpariya,no.StrategyBase
是策略的唯一基类,ITradingStrategy是它的接口。谢谢您的回答!它是否能够通过查看继承了StrategyBase的内容,自行确定战略?当用户创建一个新的策略文件以将其作为单例或工厂方法添加时,这是一项开销。ActivatorUtilities.CreateInstance?我更新了我的答案,以包含满足您需求的解决方案。
services.AddSingleton<IStrategyFactory, StrategyFactory>();
//Get all the types which are inheriting from StrategyBase class from the assembly.
var strategyTypes = Assembly.GetAssembly(typeof(StrategyBase))
    ?.GetTypes()
    .Where(type => type.IsSubclassOf(typeof(StrategyBase)));

if (strategyTypes != null)
{
    //Loop thru the types collection and register them in serviceCollection.
    foreach (var type in strategyTypes)
    {
        services.Add(new ServiceDescriptor(typeof(StrategyBase), type, ServiceLifetime.Singleton));
    }
}
public ITradingStrategy GetStrategy(string strategyName)
{
    var strategies = _serviceProvider.GetServices<StrategyBase>();

    var strategy = strategies.FirstOrDefault(s => s.GetType().Name == strategyName);

    if (strategy == null)
    {
        throw new ArgumentException($"The strategy \"{strategyName}\" could not be found.", nameof(strategyName));
    }

    return strategy;
}