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());
        }
Beispiel #2
0
        /// <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);
        }
Beispiel #3
0
        /// <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"));
            }
        }
Beispiel #6
0
        public IEndPointConfiguration GetEndPoint(string apiName)
        {
            IEndPointConfiguration result = null;

            EndPoints.TryGetValue(apiName, out result);
            return(result);
        }
Beispiel #7
0
 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);
        }
Beispiel #12
0
        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));
        }
Beispiel #13
0
        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);
        }
Beispiel #16
0
        /// <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));
        }
Beispiel #17
0
    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
     }
 }
Beispiel #20
0
 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);
        }
Beispiel #22
0
        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);
        }
Beispiel #26
0
        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);
        }
Beispiel #30
0
        /// <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);
            }
        }