/// <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> /// Resolves the actual instance of the service. /// </summary> /// <param name="solidProxyServiceProvider"></param> /// <returns></returns> public new T Resolve(SolidProxyServiceProvider solidProxyServiceProvider) { var impl = Implementations.LastOrDefault(); if (impl == null) { return(default(T)); } return(impl.Resolve(solidProxyServiceProvider)); }
/// <summary> /// Resolves all the registrations /// </summary> /// <param name="solidProxyServiceProvider"></param> /// <returns></returns> public IEnumerable ResolveAll(SolidProxyServiceProvider solidProxyServiceProvider) { var objArr = Implementations .Where(o => o.RegistrationScope != SolidProxyServiceRegistrationScope.Nonexisting) .OrderBy(o => o.RegistrationIdx) .Select(o => o.Resolve(solidProxyServiceProvider)) .ToArray(); var arr = Array.CreateInstance(ServiceType, objArr.Length); objArr.CopyTo(arr, 0); return(arr); }
/// <summary> /// Constructs a new IoC container. The parent provider may be null. /// </summary> /// <param name="parentServiceProvider"></param> public SolidProxyServiceProvider(SolidProxyServiceProvider parentServiceProvider = null) { _parentServiceProvider = parentServiceProvider; _registrations = new ConcurrentDictionary <Type, SolidProxyServiceRegistration>(); _disposeChain = new List <IDisposable>(); _containerId = RuntimeHelpers.GetHashCode(this).ToString(); AddRegistration <IServiceProvider>( NewRegistrationIdx(), SolidProxyServiceRegistrationScope.Scoped, typeof(SolidProxyServiceProvider), (sp) => this); AddRegistration <SolidProxyServiceProvider>( NewRegistrationIdx(), SolidProxyServiceRegistrationScope.Scoped, typeof(SolidProxyServiceProvider), (sp) => this); }
/// <summary> /// Resolves the object /// </summary> /// <param name="topServiceProvider"></param> /// <returns></returns> public new T Resolve(SolidProxyServiceProvider topServiceProvider) { if (!IsResolved) { lock (this) { if (!IsResolved) { if (RegistrationScope == SolidProxyServiceRegistrationScope.Singleton) { topServiceProvider = ServiceRegistration.ServiceProvider; } //Console.WriteLine($"Registration for {registration.ServiceType.FullName} not resolved. Resolving {registration.RegistrationScope}@{registration.ServiceProvider.ContainerId} from {topServiceProvider.ContainerId}"); _resolved = Resolver(topServiceProvider); IsResolved = RegistrationScope != SolidProxyServiceRegistrationScope.Transient; if (_resolved is IDisposable disposable) { topServiceProvider._disposeChain.Add(disposable); } } } } return(_resolved); }
/// <summary> /// Creates a resolver based on the implementation type. /// </summary> /// <param name="serviceProvider"></param> /// <returns></returns> private Func <SolidProxyServiceProvider, T> CreateTypedResolver(SolidProxyServiceProvider serviceProvider) { if (ImplementationType.IsGenericTypeDefinition) { return((sp) => throw new Exception("Cannot create instances of generic type definitions.")); } if (ImplementationType.IsInterface) { return((sp) => default(T)); //return (sp) => throw new Exception("Cannot create instances of interface types."); } var ctr = ImplementationType.GetConstructors() .OrderByDescending(o => o.GetParameters().Length) .Where(o => o.GetParameters().All(p => serviceProvider.CanResolve(p.ParameterType))) .FirstOrDefault(); if (ctr == null) { var paramTypes = ImplementationType.GetConstructors().SelectMany(o => o.GetParameters()).Select(o => o.ParameterType).Distinct() .Select(o => $"{o.FullName}:{serviceProvider.CanResolve(o)}").ToList(); throw new Exception($"Cannot instantiate {ImplementationType.FullName}:{string.Join(",", paramTypes)}"); } var argTypes = ctr.GetParameters().Select(o => o.ParameterType).ToArray(); return((sp) => { var args = argTypes.Select(o => serviceProvider.GetService(o)).ToArray(); if (args.Any(o => o == null)) { throw new Exception($"Cannot instantiate {ImplementationType.FullName}"); } var impl = Activator.CreateInstance(ImplementationType, args); return (T)impl; }); }
/// <summary> /// Resolves a specific type /// </summary> /// <param name="solidProxyServiceProvider"></param> /// <returns></returns> protected override object ResolveTyped(SolidProxyServiceProvider solidProxyServiceProvider) { throw new NotImplementedException("Cannot resolve generic types"); }
/// <summary> /// Creates a resolver /// </summary> /// <param name="serviceProvider"></param> /// <returns></returns> protected override Delegate CreateResolver(SolidProxyServiceProvider serviceProvider) { throw new NotImplementedException("Cannot resolve generic types"); }
/// <summary> /// Constructor /// </summary> /// <param name="serviceProvider"></param> /// <param name="serviceType"></param> public SolidProxyServiceRegistrationGeneric(SolidProxyServiceProvider serviceProvider, Type serviceType) : base(serviceProvider) { ServiceType = serviceType; }
/// <summary> /// Creates the resolver /// </summary> /// <param name="serviceProvider"></param> /// <returns></returns> protected override Delegate CreateResolver(SolidProxyServiceProvider serviceProvider) { return(CreateTypedResolver(serviceProvider)); }
/// <summary> /// Resolves the typed instance /// </summary> /// <param name="solidProxyServiceProvider"></param> /// <returns></returns> protected override object ResolveTyped(SolidProxyServiceProvider solidProxyServiceProvider) { return(Resolve(solidProxyServiceProvider)); }
/// <summary> /// Resolves the typed object /// </summary> /// <param name="solidProxyServiceProvider"></param> /// <returns></returns> protected abstract object ResolveTyped(SolidProxyServiceProvider solidProxyServiceProvider);
/// <summary> /// Resolves the object /// </summary> /// <param name="solidProxyServiceProvider"></param> /// <returns></returns> public object Resolve(SolidProxyServiceProvider solidProxyServiceProvider) { return(ResolveTyped(solidProxyServiceProvider)); }
/// <summary> /// Constructs the resolver /// </summary> /// <param name="serviceProvider"></param> /// <returns></returns> protected abstract Delegate CreateResolver(SolidProxyServiceProvider serviceProvider);
/// <summary> /// Constructor /// </summary> /// <param name="serviceProvider"></param> protected SolidProxyServiceRegistration(SolidProxyServiceProvider serviceProvider) { ServiceProvider = serviceProvider; _implementations = new List <SolidProxyServiceRegistrationImplementation>(); }
/// <summary> /// Constructor /// </summary> /// <param name="serviceProvider"></param> public SolidProxyServiceRegistration(SolidProxyServiceProvider serviceProvider) : base(serviceProvider) { }