protected override void Load(ContainerBuilder builder) { base.Load(builder); // Autofac & AdaptiveClient List <IEndPointConfiguration> endPoints = EndPointUtilities.LoadEndPoints(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "appsettings.json")).ToList(); IEndPointConfiguration backOffice = endPoints.FirstOrDefault(x => x.API_Name == API_Name.BackOffice && x.ProviderName == DataBaseProviderName.MySQL); IEndPointConfiguration frontOffice = endPoints.FirstOrDefault(x => x.API_Name == API_Name.StoreFront && x.ProviderName == DataBaseProviderName.MySQL); if (backOffice != null) { backOffice.ConnectionString = ConnectionstringUtility.BuildConnectionString(backOffice.ConnectionString); } if (frontOffice != null) { frontOffice.ConnectionString = ConnectionstringUtility.BuildConnectionString(frontOffice.ConnectionString); } builder.RegisterModule(new LeaderAnalytics.AdaptiveClient.EntityFrameworkCore.AutofacModule()); builder.RegisterInstance(endPoints).SingleInstance(); RegistrationHelper registrationHelper = new RegistrationHelper(builder); registrationHelper .RegisterEndPoints(endPoints) .RegisterModule(new Zamagon.Services.Common.AdaptiveClientModule()) .RegisterModule(new Zamagon.Services.BackOffice.AdaptiveClientModule()) .RegisterModule(new Zamagon.Services.StoreFront.AdaptiveClientModule()); }
/// <summary> /// Given an interface, we find the Perimeter with whom the interface is registered. /// Using the Perimeter, we find an EndPointConfiguration that is alive. /// Using the EndPointType and ProviderName of the resolved EndPointConfiguration, we find an implementation of T. /// </summary> /// <typeparam name="T"></typeparam> /// <returns></returns> public virtual T Create(params string[] overrideNames) { SetAvailableEndPoints(overrideNames); IEndPointConfiguration cachedEndPoint = CachedEndPoint; if (cachedEndPoint != null) { return(serviceFactory(cachedEndPoint.EndPointType, cachedEndPoint.ProviderName)); } foreach (T client in ClientEnumerator()) { IEndPointValidator validator = validatorFactory(CachedEndPoint.EndPointType, CachedEndPoint.ProviderName); if (!validator.IsInterfaceAlive(CachedEndPoint)) { if (logger != null) { logger($"Failed to connect to EndPoint named {CachedEndPoint.Name} when resolving a client of type {typeof(T)}."); } continue; } return(client); } throw new Exception($"A functional EndPointConfiguration could not be resolved for client of type {typeof(T).Name}.", null); }
/// <summary> /// Returns an instance of DbContext keyed to the API_Name of the passed IEndPointConfiguration. /// </summary> /// <param name="helper">An instance of ResolutionHelper.</param> /// <param name="ep">The IEndPointConfiguration whose properties will be used as keys.</param> /// <returns>DbContext</returns> public static DbContext ResolveDbContext(this ResolutionHelper helper, IEndPointConfiguration ep) { if (ep == null) { throw new ArgumentNullException("ep"); } IDbContextOptions options = null; try { options = ResolveDbContextOptions(helper, ep); } catch (ComponentNotRegisteredException ex) { throw new ComponentNotRegisteredException($"DbContext could not be resolved. See InnerException for additional detail.", ex); } DbContext context = helper.scope.ResolveOptionalKeyed <DbContext>(ep.API_Name, new TypedParameter(typeof(DbContextOptions), options.Options)); if (context == null) { throw new ComponentNotRegisteredException($"DbContext could not be resolved for API_Name {ep.API_Name}. Call RegisterDbContext with an API_Name of {ep.API_Name} to register the required component."); } return(context); }
public async Task Services_are_resolved_on_service_manifest() { // PaymentsService calls AccountsService internally. // In this test we mock AccountService so we know it is resolved and accessible from within PaymentsService. IEndPointConfiguration ep = EndPoints.First(x => x.ProviderName == CurrentDatabaseProviderName && x.API_Name == API_Name.BackOffice); await DropAndRecreate(ep); Mock <IAccountsService> fakeMSSQLAccountsService = new Mock <IAccountsService>(); fakeMSSQLAccountsService.Setup(x => x.GetAccountByID(It.IsAny <int>())).ReturnsAsync(new Account { Name = "TEST" }); using (var scope = Container.BeginLifetimeScope(builder => { builder.RegisterInstance(fakeMSSQLAccountsService.Object).Keyed <IAccountsService>(EndPointType.DBMS + CurrentDatabaseProviderName); })) { IAdaptiveClient <IBOServiceManifest> client = scope.Resolve <IAdaptiveClient <IBOServiceManifest> >(); Account account = await client.CallAsync(x => x.PaymentsService.GetAccountForPaymentID(1), ep.Name); Assert.AreEqual("TEST", account.Name); } }
public void Resolve_DbContext_for_API() { IEndPointConfiguration storeFrontep = EndPoints.First(x => x.ProviderName == CurrentDatabaseProviderName && x.API_Name == API_Name.StoreFront); IEndPointConfiguration backOfficeep = EndPoints.First(x => x.ProviderName == CurrentDatabaseProviderName && x.API_Name == API_Name.BackOffice); ResolutionHelper resolutionHelper = Container.Resolve <ResolutionHelper>(); DbContext storeFrontContext = resolutionHelper.ResolveDbContext(storeFrontep); DbContext backOfficeContext = resolutionHelper.ResolveDbContext(backOfficeep); Assert.IsNotNull(storeFrontContext); Assert.IsNotNull(backOfficeContext); Assert.IsTrue(storeFrontContext is Artifacts.StoreFront.Db); Assert.IsTrue(backOfficeContext is Artifacts.BackOffice.Db); if (CurrentDatabaseProviderName == DataBaseProviderName.MSSQL) { Assert.IsTrue(storeFrontContext.Database.GetDbConnection().ConnectionString == storeFrontep.ConnectionString); Assert.IsTrue(backOfficeContext.Database.GetDbConnection().ConnectionString == backOfficeep.ConnectionString); } else if (CurrentDatabaseProviderName == DataBaseProviderName.MySQL) { // MySql database connector changes the connection string. Assert.IsTrue(storeFrontContext.Database.GetDbConnection().ConnectionString.ToLower().Contains("database=adaptiveclientef_storefront")); Assert.IsTrue(backOfficeContext.Database.GetDbConnection().ConnectionString.ToLower().Contains("database=adaptiveclientef_backoffice")); } }
public IEndPointConfiguration GetEndPoint(string apiName) { IEndPointConfiguration result = null; EndPoints.TryGetValue(apiName, out result); return(result); }
public AddProfileAction( IProfileRepository profileRepository, IEndPointConfiguration endPointConfiguration, IDockerClientFactory dockerClientFactory) { _profileRepository = profileRepository; _endPointConfiguration = endPointConfiguration; _dockerClientFactory = dockerClientFactory; }
public async Task Employee_count_equals_two() { IEndPointConfiguration ep = EndPoints.First(x => x.ProviderName == CurrentDatabaseProviderName && x.API_Name == API_Name.BackOffice); await DropAndRecreateDatabase(ep); List <Employee> employees = await BOServiceClient.CallAsync(async x => await x.EmployeesService.GetEmployees(), ep.Name); Assert.AreEqual(2, employees.Count); }
protected async Task DropAndRecreate(IEndPointConfiguration ep) { using (ILifetimeScope scope = Container.BeginLifetimeScope()) { IDatabaseUtilities databaseUtilities = Container.Resolve <IDatabaseUtilities>(); await databaseUtilities.DropDatabase(ep); await databaseUtilities.ApplyMigrations(ep); } }
public async Task Product_count_equals_two() { IEndPointConfiguration ep = EndPoints.First(x => x.ProviderName == CurrentDatabaseProviderName && x.API_Name == API_Name.StoreFront); await DropAndRecreateDatabase(ep); List <Product> products = await SFServiceClient.CallAsync(async x => await x.ProductsService.GetProducts(), ep.Name); Assert.AreEqual(2, products.Count); }
public async Task TimeCard_count_equals_four() { IEndPointConfiguration ep = EndPoints.First(x => x.ProviderName == CurrentDatabaseProviderName && x.API_Name == API_Name.BackOffice); await DropAndRecreateDatabase(ep); List <TimeCard> timeCards = await BOServiceClient.CallAsync(async x => await x.TimeCardsService.GetTimeCards(), ep.Name); Assert.AreEqual(4, timeCards.Count); }
public static IProxyService Create(IEndPointConfiguration from, IEndPointConfiguration to, Action <string> log) { ProxyServiceFactory serviceFactory; if (!ServiceFactoriesByProtocolPair.TryGetValue(Tuple.Create(from.GetType(), to.GetType()), out serviceFactory)) { throw new ProxyServiceResolutionException($"No proxy service is registered from {from.GetType().Name} to {to.GetType().Name}."); } return(serviceFactory.Invoke(from, to, log)); }
protected async Task DropAndRecreateDatabase(IEndPointConfiguration ep) { if (ep.EndPointType != EndPointType.DBMS) { return; } await DatabaseUtilities.DropDatabase(ep); await DatabaseUtilities.ApplyMigrations(ep); }
public BaseHTTPService(Func <IEndPointConfiguration> endPointFactory) { endPoint = endPointFactory(); if (endPoint.EndPointType == EndPointType.HTTP) { httpClient = new HttpClient { BaseAddress = new Uri(endPoint.ConnectionString) } } ; }
public void Resolve_DatabaseInitalizer_for_API() { IEndPointConfiguration storeFrontep = EndPoints.First(x => x.ProviderName == CurrentDatabaseProviderName && x.API_Name == API_Name.StoreFront); IEndPointConfiguration backOfficeep = EndPoints.First(x => x.ProviderName == CurrentDatabaseProviderName && x.API_Name == API_Name.BackOffice); ResolutionHelper resolutionHelper = Container.Resolve <ResolutionHelper>(); IDatabaseInitializer storeFrontInitalizer = resolutionHelper.ResolveDatabaseInitializer(storeFrontep); IDatabaseInitializer backOfficeInitalizer = resolutionHelper.ResolveDatabaseInitializer(backOfficeep); Assert.IsTrue(storeFrontInitalizer is Artifacts.StoreFront.SFDatabaseInitializer); Assert.IsTrue(backOfficeInitalizer is Artifacts.BackOffice.BODatabaseInitializer); }
/// <summary> /// This overload is primarily for internal use by AdaptiveClient. Resolves an implementation of IDbContextOptions using /// EndPointContext.CurrentEndPoint which is set internally by AdaptiveClient. /// </summary> /// <param name="helper">An instance of ResolutionHelper.</param> /// <returns>An implementation of IDbContextOptions</returns> public static IDbContextOptions ResolveDbContextOptions(this ResolutionHelper helper) { Func <IEndPointConfiguration> epFactory = helper.scope.Resolve <Func <IEndPointConfiguration> >(); // Registered by AdaptiveClient. Returns EndPointContext.CurrentEndPoint IEndPointConfiguration ep = epFactory(); if (ep == null) { throw new Exception("EndPointContext.CurrentEndPoint is null."); } return(ResolveDbContextOptions(helper, ep)); }
public void DisplayUserName(IEndPointConfiguration endPoint) { // We need to pass in the endPoint because this is a demo and the endPoint is selected // at runtime. In a real application AdaptiveClient will read the EndPoints file // and use the active EndPoint. // Here we simulate making a call to an API server. Adaptive Client will use // properties of the endPoint to resolve the correct implementation of IUsersService. User user = client.Try(usersService => usersService.GetUserByID(1), endPoint.Name); Console.WriteLine(user?.Name); }
/// <summary> /// Creates a database if it does not exist and/or applies pending migrations, if any. /// </summary> /// <param name="ep">The IEndPointConfiguration whose properties will be used as keys.</param> /// <returns>DatabaseValidationResult</returns> public virtual async Task <DatabaseValidationResult> CreateOrUpdateDatabase(IEndPointConfiguration endPoint) { DatabaseValidationResult result = new DatabaseValidationResult(); DatabaseStatus status = await GetDatabaseStatus(endPoint); result.DatabaseWasCreated = status == DatabaseStatus.DoesNotExist; if (status != DatabaseStatus.ConsistentWithModel) { result.AppliedMigrations = await ApplyMigrations(endPoint); } return(result); }
public static void AddConfiguration(IEndPointConfiguration config) { try { var container = Startup.Container; container.RemoveAll<IEndPointConfiguration>(); container.Register<IEndPointConfiguration>(c => config); ServiceLocator.SetLocatorProvider(() => container); } catch (Exception) { // Ignore exceptions here - just means something already registered this type } }
public static void AddConfiguration(IEndPointConfiguration config) { try { var container = Startup.Container; container.RemoveAll <IEndPointConfiguration>(); container.Register <IEndPointConfiguration>(c => config); ServiceLocator.SetLocatorProvider(() => container); } catch (Exception) { // Ignore exceptions here - just means something already registered this type } }
/// <summary> /// Checks if a database exists or if there are pending migrations. /// </summary> /// <param name="ep">The IEndPointConfiguration whose properties will be used as keys.</param> /// <returns>DatabaseStatus</returns> public virtual async Task <DatabaseStatus> GetDatabaseStatus(IEndPointConfiguration endPoint) { DbContext context = resolver.ResolveMigrationContext(endPoint); if (!await((context.Database.GetService <IDatabaseCreator>() as RelationalDatabaseCreator).ExistsAsync())) { return(DatabaseStatus.DoesNotExist); } if ((await context.Database.GetPendingMigrationsAsync()).Any()) { return(DatabaseStatus.NotConsistentWithModel); } return(DatabaseStatus.ConsistentWithModel); }
public void SetEndPoint(string apiName, IEndPointConfiguration endPoint) { if (string.IsNullOrEmpty(apiName)) { throw new ArgumentNullException(apiName); } if (endPoint == null) { EndPoints.TryRemove(apiName, out IEndPointConfiguration dummy); } else { EndPoints[apiName] = endPoint; } }
public virtual bool IsInterfaceAlive(IEndPointConfiguration endPoint) { bool result = true; using (MySqlConnection con = new MySqlConnection(endPoint.ConnectionString)) { try { con.Open(); // must specify an existing database name in connection string or it throws. } catch (Exception) { result = false; } } return(result); }
public void Resolve_DbContextOptions_for_provider() { IEndPointConfiguration ep = EndPoints.First(x => x.ProviderName == CurrentDatabaseProviderName); ResolutionHelper resolutionHelper = Container.Resolve <ResolutionHelper>(); IDbContextOptions options = resolutionHelper.ResolveDbContextOptions(ep); Assert.IsNotNull(options); if (CurrentDatabaseProviderName == DataBaseProviderName.MSSQL) { Assert.IsTrue(options is Artifacts.DbContextOptions_MSSQL); } else if (CurrentDatabaseProviderName == DataBaseProviderName.MySQL) { Assert.IsTrue(options is Artifacts.DbContextOptions_MySQL); } }
public virtual bool IsInterfaceAlive(IEndPointConfiguration endPoint) { bool result = true; using (SqlConnection con = new SqlConnection(endPoint.ConnectionString)) { try { con.Open(); } catch (Exception) { result = false; } } return(result); }
public static IEnumerable <IEndPointConfiguration> ReadEndPointsFromDisk() { List <IEndPointConfiguration> endPoints = EndPointUtilities.LoadEndPoints(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "appsettings.json")).ToList(); IEndPointConfiguration backOffice = endPoints.FirstOrDefault(x => x.API_Name == API_Name.BackOffice && x.ProviderName == DataBaseProviderName.MySQL); IEndPointConfiguration frontOffice = endPoints.FirstOrDefault(x => x.API_Name == API_Name.StoreFront && x.ProviderName == DataBaseProviderName.MySQL); if (backOffice != null) { backOffice.ConnectionString = ConnectionstringUtility.BuildConnectionString(endPoints.First(x => x.API_Name == API_Name.BackOffice && x.ProviderName == DataBaseProviderName.MySQL).ConnectionString); } if (frontOffice != null) { frontOffice.ConnectionString = ConnectionstringUtility.BuildConnectionString(endPoints.First(x => x.API_Name == API_Name.StoreFront && x.ProviderName == DataBaseProviderName.MySQL).ConnectionString); } return(endPoints); }
private void GetUser() { IEndPointConfiguration endPoint = EndPoints.First(x => x.Name == SelectedEndPointName); Logger.Message = null; if (SelectedEndPointName == "Prod_WCF_01") { // This end point was registered with mocks so it will fail and fall back to Prod_MSSQL_01 // If the current endpoint is Prod_MSSQL_01 you won't see an error message because AdaptiveClient // will continue to use that endpoint. DemoUser = client.Try(usersService => usersService.GetUserByID(1), endPoint.Name, "Prod_MSSQL_01"); } else { DemoUser = client.Call(usersService => usersService.GetUserByID(1), endPoint.Name); } }
static void Main(string[] args) { List <IEndPointConfiguration> endPoints = EndPointUtilities.LoadEndPoints("appsettings.json").ToList(); ContainerBuilder builder = new ContainerBuilder(); AutofacModule.RegisterComponents(builder); IContainer container = builder.Build(); Console.Clear(); DisplayIntro(); int i = 0; endPoints.ForEach(ep => Console.WriteLine($"{i++}. {ep.Name}")); Console.WriteLine(); while (true) { int cursorRow = 13; SetCursorToRow(cursorRow++); Console.Write("Choose an EndPoint (connection string) from the list or enter Q to exit:"); ConsoleKeyInfo lastKey = Console.ReadKey(); if (lastKey.Key == ConsoleKey.Q) { break; } bool isParsed = int.TryParse(lastKey.KeyChar.ToString(), out int index); if (!isParsed || index >= endPoints.Count) { continue; } SetCursorToRow(cursorRow++); IEndPointConfiguration ep = endPoints[index]; Demo demo = container.Resolve <Demo>(); demo.DisplayUserName(ep); } Console.WriteLine("Adaptive Client demo ended."); }
/// <summary> /// Applies pending migrations, if any. /// </summary> /// <param name="ep">The IEndPointConfiguration whose properties will be used as keys.</param> /// <returns>A list of names of migrations that were applied.</returns> public virtual async Task <List <string> > ApplyMigrations(IEndPointConfiguration endPoint) { DbContext context = resolver.ResolveMigrationContext(endPoint); IDatabaseInitializer dataInitializer = resolver.ResolveDatabaseInitializer(endPoint); List <string> migrations = (await context.Database.GetPendingMigrationsAsync()).ToList(); IMigrator migrator = context.Database.GetService <IMigrator>(); foreach (string migrationName in migrations) { await migrator.MigrateAsync(migrationName); if (dataInitializer != null) { await dataInitializer.Seed(migrationName); } } return(migrations); }
/// <summary> /// Given an interface, we find the Perimeter with whom the interface is registered. /// Using the Perimeter, we find an EndPointConfiguration that is alive. /// Using the EndPointType and ProviderName of the resolved EndPointConfiguration, we find an implementation of T. /// </summary> /// <typeparam name="T"></typeparam> /// <returns></returns> public virtual T Create(params string[] overrideNames) { SetAvailableEndPoints(overrideNames); IEndPointConfiguration cachedEndPoint = CachedEndPoint; if (cachedEndPoint != null) { return(serviceFactory(cachedEndPoint.EndPointType, cachedEndPoint.ProviderName)); } foreach (T client in ClientEnumerator()) { bool?validationResult = endPointCache.GetValidationResult(CachedEndPoint.Name); if (validationResult.HasValue) // .HasValue when validated previously { if (validationResult.Value) { return(client); } else { continue; } } IEndPointValidator validator = validatorFactory(CachedEndPoint.EndPointType, CachedEndPoint.ProviderName); bool isAlive = validator.IsInterfaceAlive(CachedEndPoint); endPointCache.SetValidationResult(CachedEndPoint.Name, isAlive); if (!isAlive) { logger?.Invoke($"Failed to connect to EndPoint named {CachedEndPoint.Name} when resolving a client of type {typeof(T)}."); continue; } return(client); } throw new Exception($"A functional EndPointConfiguration could not be resolved for client of type {typeof(T).Name}.", null); }
public void Resolve_MigrationHelper_for_API() { IEndPointConfiguration storeFrontep = EndPoints.First(x => x.ProviderName == CurrentDatabaseProviderName && x.API_Name == API_Name.StoreFront); IEndPointConfiguration backOfficeep = EndPoints.First(x => x.ProviderName == CurrentDatabaseProviderName && x.API_Name == API_Name.BackOffice); ResolutionHelper resolutionHelper = Container.Resolve <ResolutionHelper>(); DbContext storeFrontContext = resolutionHelper.ResolveMigrationContext(storeFrontep); DbContext backOfficeContext = resolutionHelper.ResolveMigrationContext(backOfficeep); Assert.IsNotNull(storeFrontContext); Assert.IsNotNull(backOfficeContext); if (CurrentDatabaseProviderName == DataBaseProviderName.MSSQL) { Assert.IsTrue(storeFrontContext is Artifacts.StoreFront.Db_MSSQL); Assert.IsTrue(backOfficeContext is Artifacts.BackOffice.Db_MSSQL); } else if (CurrentDatabaseProviderName == DataBaseProviderName.MySQL) { Assert.IsTrue(storeFrontContext is Artifacts.StoreFront.Db_MySQL); Assert.IsTrue(backOfficeContext is Artifacts.BackOffice.Db_MySQL); } }