public ServiceKey(Type serviceType, ServiceDefinition definition) { ServiceType = serviceType; ImplementType = definition.GetImplementType(); }
private object GetServiceInstance(Type serviceType, ServiceDefinition serviceDefinition) => EnrichObject(GetServiceInstanceInternal(serviceType, serviceDefinition));
private object GetServiceInstanceInternal(Type serviceType, ServiceDefinition serviceDefinition) { if (serviceDefinition.ImplementationInstance != null) { return(serviceDefinition.ImplementationInstance); } if (serviceDefinition.ImplementationFactory != null) { return(serviceDefinition.ImplementationFactory.Invoke(this)); } var implementType = (serviceDefinition.ImplementType ?? serviceType); if (implementType.IsInterface || implementType.IsAbstract) { throw new InvalidOperationException($"invalid service registered, serviceType: {serviceType.FullName}, implementType: {serviceDefinition.ImplementType}"); } if (implementType.IsGenericType) { implementType = implementType.MakeGenericType(serviceType.GetGenericArguments()); } var newFunc = CacheUtil.TypeNewFuncCache.GetOrAdd(implementType, (serviceContainer) => { if (CacheUtil.TypeEmptyConstructorFuncCache.TryGetValue(implementType, out var emptyFunc)) { return(emptyFunc.Invoke()); } var ctor = CacheUtil.TypeConstructorCache.GetOrAdd(implementType, t => { var ctorInfos = t.GetConstructors(BindingFlags.Instance | BindingFlags.Public); if (ctorInfos.Length == 0) { return(null); } ConstructorInfo ctorInfo; if (ctorInfos.Length == 1) { ctorInfo = ctorInfos[0]; } else { ctorInfo = ctorInfos.FirstOrDefault(x => x.IsDefined(typeof(ServiceConstructorAttribute))) ?? ctorInfos .OrderBy(_ => _.GetParameters().Length) .First(); } return(ctorInfo); }); if (ctor == null) { throw new InvalidOperationException( $"service {serviceType.FullName} does not have any public constructors"); } var parameters = ctor.GetParameters(); if (parameters.Length == 0) { var func00 = Expression.Lambda <Func <object> >(Expression.New(ctor)).Compile(); CacheUtil.TypeEmptyConstructorFuncCache.TryAdd(implementType, func00); return(func00.Invoke()); } var ctorParams = new object[parameters.Length]; for (var index = 0; index < parameters.Length; index++) { var param = serviceContainer.GetService(parameters[index].ParameterType); if (param == null && parameters[index].HasDefaultValue) { param = parameters[index].DefaultValue; } ctorParams[index] = param; } var func = CacheUtil.TypeConstructorFuncCache.GetOrAdd(implementType, t => { if (!CacheUtil.TypeConstructorCache.TryGetValue(t, out var ctorInfo)) { return(null); } var innerParameters = ctorInfo.GetParameters(); var parameterExpression = Expression.Parameter(typeof(object[]), "arguments"); // create parameter Expression var argExpressions = new Expression[innerParameters.Length]; // array that will contains parameter expessions for (var i = 0; i < innerParameters.Length; i++) { var indexedAccess = Expression.ArrayIndex(parameterExpression, Expression.Constant(i)); if (!innerParameters[i].ParameterType.IsClass) { // we should create local variable that will store parameter value var localVariable = Expression.Variable(innerParameters[i].ParameterType, "localVariable"); var block = Expression.Block(new[] { localVariable }, Expression.IfThenElse(Expression.Equal(indexedAccess, Expression.Constant(null)), Expression.Assign(localVariable, Expression.Default(innerParameters[i].ParameterType)), Expression.Assign(localVariable, Expression.Convert(indexedAccess, innerParameters[i].ParameterType)) ), localVariable ); argExpressions[i] = block; } else { argExpressions[i] = Expression.Convert(indexedAccess, innerParameters[i].ParameterType); } } // create expression that represents call to specified ctor with the specified arguments. var newExpression = Expression.New(ctorInfo, argExpressions); return(Expression.Lambda <Func <object[], object> >(newExpression, parameterExpression) .Compile()); }); return(func.Invoke(ctorParams)); }); return(newFunc?.Invoke(this)); }
public static IServiceContainer AddTransient <TService>([NotNull] this IServiceContainer serviceContainer) { serviceContainer.Add(ServiceDefinition.Transient <TService>()); return(serviceContainer); }
public static IServiceContainer AddTransient <TService, TServiceImplement>([NotNull] this IServiceContainer serviceContainer) where TServiceImplement : TService { serviceContainer.Add(ServiceDefinition.Transient <TService, TServiceImplement>()); return(serviceContainer); }
public static IServiceContainer AddScoped <TService>([NotNull] this IServiceContainer serviceContainer) { serviceContainer.Add(ServiceDefinition.Scoped <TService>()); return(serviceContainer); }
public static IServiceContainer AddTransient <TService>([NotNull] this IServiceContainer serviceContainer, [NotNull] Func <IServiceProvider, object> func) { serviceContainer.Add(ServiceDefinition.Transient <TService>(func)); return(serviceContainer); }
public static IServiceContainer TryAddScoped <TService, TServiceImplement>([NotNull] this IServiceContainer serviceContainer) where TServiceImplement : TService { serviceContainer.TryAdd(ServiceDefinition.Scoped <TService, TServiceImplement>()); return(serviceContainer); }
public static IServiceContainer TryAddScoped <TService>([NotNull] this IServiceContainer serviceContainer, [NotNull] Func <IServiceProvider, object> func) { serviceContainer.TryAdd(ServiceDefinition.Scoped <TService>(func)); return(serviceContainer); }
public static IServiceContainer TryAddSingleton <TService>([NotNull] this IServiceContainer serviceContainer) { serviceContainer.TryAdd(ServiceDefinition.Singleton <TService>()); return(serviceContainer); }
public static IServiceContainerBuilder AddSingleton <TService, TServiceImplement>([NotNull] this IServiceContainerBuilder serviceContainerBuilder) where TServiceImplement : TService { serviceContainerBuilder.Add(ServiceDefinition.Singleton <TService, TServiceImplement>()); return(serviceContainerBuilder); }
public static IServiceContainerBuilder AddSingleton <TService>([NotNull] this IServiceContainerBuilder serviceContainerBuilder, [NotNull] Func <IServiceProvider, object> func) { serviceContainerBuilder.Add(ServiceDefinition.Singleton <TService>(func)); return(serviceContainerBuilder); }