internal BotState Build() { // WARNING: taming of reflection dragons ahead var botState = default(BotState); if (_botStateFactory == null) { if (_storage == null) { throw new InvalidOperationException($"No {nameof(IStorage)} implementation has been specified. Either specify one using {nameof(UseStorage)}, or supply a custom {nameof(BotState)} factory with {nameof(UseBotStateFactory)}."); } botState = (BotState)Activator.CreateInstance(typeof(TBotState), _storage); } else { botState = _botStateFactory.Invoke(); if (botState == default(BotState)) { throw new InvalidOperationException($"The specified bot state factory returned a null {nameof(BotState)} instance."); } } // TODO: should be an overload of CreateProperty that takes Type! var createPropertyGenericMethodInfo = typeof(BotState).GetMethod("CreateProperty").GetGenericMethodDefinition(); var statePropertyAccessorGenericInterface = typeof(IStatePropertyAccessor <>); var services = _botStateConfigurationBuilder.Services; foreach (var entry in _properties) { var createPropertyMethodInfo = createPropertyGenericMethodInfo.MakeGenericMethod(entry.Value); var propertyAccessor = createPropertyMethodInfo.Invoke(botState, new[] { entry.Key }); services.AddSingleton(statePropertyAccessorGenericInterface.MakeGenericType(entry.Value), propertyAccessor); } _botStateConfigurationBuilder.UseBotState(botState); return(botState); }
private static BotStateConfigurationBuilder UseBotState <TBotState>(BotStateConfigurationBuilder builder, Action <BotStateBuilder <TBotState> > configure) where TBotState : BotState { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (configure == null) { throw new ArgumentNullException(nameof(configure)); } var stateBuilder = new BotStateBuilder <TBotState>(builder); configure(stateBuilder); var botState = stateBuilder.Build(); return(builder.UseBotState(botState)); }