/// <summary> /// Configures a proxy /// </summary> /// <typeparam name="TProxy"></typeparam> /// <param name="serviceProvider"></param> /// <param name="interfaceConfig"></param> public static void ConfigureProxyInternal <TProxy>(SolidProxyServiceProvider serviceProvider, ISolidInterfaceConfigurationBuilder <TProxy> interfaceConfig) where TProxy : class { if (serviceProvider.Registrations.Any(o => o.ServiceType != typeof(TProxy))) { serviceProvider.AddScoped <TProxy, TProxy>(); } var registrationImpls = serviceProvider.Registrations .Where(o => o.ServiceType == typeof(TProxy)) .SelectMany(o => o.Implementations).ToList(); foreach (var registration in registrationImpls) { // check if this registration is mapped to the solid proxy. var implementationFactoryTarget = registration.Resolver?.Target; if (implementationFactoryTarget == s_proxyFactoryFactory) { continue; } var registrationGuid = Guid.NewGuid(); var proxyGenerator = serviceProvider.GetRequiredService <ISolidProxyGenerator>(); Func <IServiceProvider, TProxy> implementationFactory = null; // // add the configuration for the proxy and register // proxy and interface the same way as the removed service. // switch (registration.RegistrationScope) { case SolidProxyServiceRegistrationScope.Scoped: serviceProvider.AddScoped(s_proxyFactoryFactory.CreateProxyFactory(proxyGenerator, implementationFactory)); break; case SolidProxyServiceRegistrationScope.Transient: serviceProvider.AddTransient(s_proxyFactoryFactory.CreateProxyFactory(proxyGenerator, implementationFactory)); break; case SolidProxyServiceRegistrationScope.Singleton: serviceProvider.AddSingleton(s_proxyFactoryFactory.CreateProxyFactory(proxyGenerator, implementationFactory)); break; } // // make sure that all the methods are configured // if (typeof(TProxy) != typeof(ISolidProxyInvocationImplAdviceConfig)) { typeof(TProxy).GetMethods().ToList().ForEach(m => { var methodConfig = interfaceConfig.ConfigureMethod(m); methodConfig.ConfigureAdvice <ISolidProxyInvocationImplAdviceConfig>(); methodConfig.AddAdvice(typeof(SolidProxyInvocationImplAdvice <, ,>)); }); } } ; }
/// <summary> /// Configures the proxy /// </summary> /// <typeparam name="TProxy"></typeparam> /// <param name="interfaceConfig"></param> public override void ConfigureProxy <TProxy>(ISolidInterfaceConfigurationBuilder <TProxy> interfaceConfig) { var services = ServiceCollection.Where(o => o.ServiceType == typeof(TProxy)).ToList(); foreach (var service in services) { // // check if this service has been configured already. // var implementationFactoryTarget = service.ImplementationFactory?.Target?.GetType()?.DeclaringType; if (implementationFactoryTarget == GetType()) { continue; } // remove the service difinition - added again later ServiceCollection.Remove(service); // // create implementation factory function. // Func <IServiceProvider, TProxy> implementationFactory = null; if (service.ImplementationFactory != null) { implementationFactory = sp => (TProxy)service.ImplementationFactory.Invoke(sp); } else if (service.ImplementationInstance != null) { implementationFactory = sp => (TProxy)service.ImplementationInstance; } else if (service.ImplementationType != null) { if (service.ImplementationType.IsClass) { DoIfMissing(service.ImplementationType, () => ServiceCollection.Add(new ServiceDescriptor(service.ImplementationType, service.ImplementationType, service.Lifetime))); implementationFactory = sp => (TProxy)sp.GetRequiredService(service.ImplementationType); } else { implementationFactory = null; } } else { throw new Exception("Cannot determine implementation type"); } Func <IServiceProvider, ISolidProxied <TProxy> > proxiedFactory = (sp) => new SolidProxied <TProxy>(implementationFactory(sp)); // // add the configuration for the proxy and register // proxy and interface the same way as the removed service. // var proxyGenerator = SolidProxyGenerator; var config = new SolidProxyConfig <TProxy>(implementationFactory); ServiceCollection.AddSingleton(config.GetProxyConfiguration); Func <IServiceProvider, TProxy> proxyFactory = (sp) => { return(proxyGenerator.CreateSolidProxy(sp, config.GetProxyConfiguration(sp)).Proxy); }; switch (service.Lifetime) { case ServiceLifetime.Scoped: ServiceCollection.AddScoped(proxyFactory); ServiceCollection.AddScoped(proxiedFactory); break; case ServiceLifetime.Transient: ServiceCollection.AddTransient(proxyFactory); ServiceCollection.AddTransient(proxiedFactory); break; case ServiceLifetime.Singleton: ServiceCollection.AddSingleton(proxyFactory); ServiceCollection.AddSingleton(proxiedFactory); break; } } ; // // make sure that all the methods are configured // var proxyMethods = GetProxyMethods <TProxy>(); foreach (var m in proxyMethods) { var methodConfig = interfaceConfig.ConfigureMethod(m); methodConfig.ConfigureAdvice <ISolidProxyInvocationImplAdviceConfig>(); } }