Beispiel #1
0
 public ServiceKey(Type serviceType, ServiceDefinition definition)
 {
     ServiceType   = serviceType;
     ImplementType = definition.GetImplementType();
 }
Beispiel #2
0
 private object GetServiceInstance(Type serviceType, ServiceDefinition serviceDefinition)
 => EnrichObject(GetServiceInstanceInternal(serviceType, serviceDefinition));
Beispiel #3
0
        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));
        }
Beispiel #4
0
 public static IServiceContainer AddTransient <TService>([NotNull] this IServiceContainer serviceContainer)
 {
     serviceContainer.Add(ServiceDefinition.Transient <TService>());
     return(serviceContainer);
 }
Beispiel #5
0
 public static IServiceContainer AddTransient <TService, TServiceImplement>([NotNull] this IServiceContainer serviceContainer) where TServiceImplement : TService
 {
     serviceContainer.Add(ServiceDefinition.Transient <TService, TServiceImplement>());
     return(serviceContainer);
 }
Beispiel #6
0
 public static IServiceContainer AddScoped <TService>([NotNull] this IServiceContainer serviceContainer)
 {
     serviceContainer.Add(ServiceDefinition.Scoped <TService>());
     return(serviceContainer);
 }
Beispiel #7
0
 public static IServiceContainer AddTransient <TService>([NotNull] this IServiceContainer serviceContainer, [NotNull] Func <IServiceProvider, object> func)
 {
     serviceContainer.Add(ServiceDefinition.Transient <TService>(func));
     return(serviceContainer);
 }
Beispiel #8
0
 public static IServiceContainer TryAddScoped <TService, TServiceImplement>([NotNull] this IServiceContainer serviceContainer) where TServiceImplement : TService
 {
     serviceContainer.TryAdd(ServiceDefinition.Scoped <TService, TServiceImplement>());
     return(serviceContainer);
 }
Beispiel #9
0
 public static IServiceContainer TryAddScoped <TService>([NotNull] this IServiceContainer serviceContainer, [NotNull] Func <IServiceProvider, object> func)
 {
     serviceContainer.TryAdd(ServiceDefinition.Scoped <TService>(func));
     return(serviceContainer);
 }
Beispiel #10
0
 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);
 }