private Expression GetObjectFromSelf(Type interfaceType, ServiceRegister registrar, ServiceState state, string serviceName) { var serviceInfo = GetServiceInfo(interfaceType, serviceName); if (serviceInfo == null) { ExceptionHelper.ThrowContractNotRegisteredException(interfaceType.FullName); } var instanceCallback = serviceInfo.GetServiceInstanceCallback <object>(); if (instanceCallback != null) { throw new Exception("Internal service injection does not support for Func<> delegate."); } var expression = serviceInfo.GetServiceInstanceExpression(); if (expression == null) { expression = CreateConstructorExpression(interfaceType, serviceInfo.ServiceType, registrar, state); } return(expression); }
private Expression GetDependencyObject(ParameterInfo constrParameter, ServiceRegister registrar, IgnoreAttribute ignoreAttribute, ServiceState state) { bool ignore = ignoreAttribute?.ParameterNames.Contains(constrParameter.Name) ?? false; if (ignore) { return(Expression.Default(constrParameter.ParameterType)); } else { var mappedServiceName = GetMappedServiceName(constrParameter); /* * if container model is "Single" then it will search within the same container not in dependencies. * if parameter is decorated with FromSelfAttribute, then find object within the current factory */ if (IsSelfDependent(constrParameter)) { //Find it in same return(GetObjectFromSelf(constrParameter.ParameterType, registrar, state, mappedServiceName)); } /*if parameter is decorated with FromDependencyAttribute, then find object within the specified factory */ string factoryName; if (HasDependencyAttribute(constrParameter, out factoryName)) { return(GetObjectFromDependencyFactory(constrParameter.ParameterType, factoryName, registrar, state, mappedServiceName, new TypeContextAttributes(constrParameter.GetCustomAttributes()))); } //let's subcontract take responsibility to create dependency objects return(CreateDependency(constrParameter.ParameterType, registrar, state, mappedServiceName, new TypeContextAttributes(constrParameter.GetCustomAttributes()))); } }
/// <summary> /// Create <see cref="Expression"/> for service which is associated with contract. /// </summary> /// <param name="interfaceType">Type of contract</param> /// <param name="register">The ServiceRegister</param> /// <param name="state">The ServiceState</param> /// <param name="serviceName"></param> /// <param name="attributes"></param> /// <returns>Returns <see cref="Expression"/> of service constructor.</returns> public override Expression Create(Type interfaceType, ServiceRegister register, ServiceState state, string serviceName, TypeContextAttributes attributes) { if (interfaceType == null) { throw new ArgumentNullException(nameof(interfaceType)); } //Register current subcontract service with ServiceRegistrar //Root service will refresh with the updated service when there's replacement with new service register.Register(interfaceType); BaseServiceInfo serviceMeta = GetServiceInfo(interfaceType, serviceName); if (serviceMeta == null) { return(SharedFactory.Create(interfaceType, register, state, serviceName, attributes)); } var userdefinedExpression = serviceMeta.GetServiceInstanceExpression(); if (userdefinedExpression != null) { return(Expression.Invoke(userdefinedExpression)); } return(CreateConstructorExpression(interfaceType, serviceMeta.ServiceType, register, state) ?? Expression.Default(interfaceType)); }
/// <summary> /// Create <see cref="Expression"/> for service which is associated with contract. /// </summary> /// <param name="interfaceType">Type of contract</param> /// <param name="register">The ServiceRegister</param> /// <param name="state">The ServiceState</param> /// <param name="serviceName"></param> /// <param name="attributes"></param> /// <returns>Returns <see cref="Expression"/> of service constructor.</returns> public override Expression Create(Type interfaceType, ServiceRegister register, ServiceState state, string serviceName, TypeContextAttributes attributes) { if (interfaceType == null) { throw new ArgumentNullException(nameof(interfaceType)); } //Register current subcontract service with ServiceRegistrar //Root service will refresh with the updated service when there's replacement with new service register.Register(interfaceType); BaseServiceInfo serviceMeta = GetServiceInfo(interfaceType, serviceName); //Throw exception if service meta not found in the service map table if (serviceMeta == null) { if (attributes.HasAttribute(typeof(OptionalAttribute))) { return(Expression.Default(interfaceType)); } else { ExceptionHelper.ThrowContractNotRegisteredException($"Type '{interfaceType.FullName}' was not registered with dependency container or shared container."); } } var userdefinedExpression = serviceMeta.GetServiceInstanceExpression(); if (userdefinedExpression != null) { return(Expression.Invoke(userdefinedExpression)); } return(CreateConstructorExpression(interfaceType, serviceMeta.ServiceType, register, state) ?? Expression.Default(interfaceType)); }
/// <summary> /// Creates dependency <see cref="Expression"/> object. if no dependency factory is set and shared factory exists then /// creates dependency from the shared factory; otherwise creates from the dependency factory. /// </summary> /// <param name="interfaceType">The type of the contract.</param> /// <param name="register">The service register object.</param> /// <param name="state">The service state.</param> /// <param name="serviceName"></param> /// <param name="attributes"></param> /// <returns>Dependency expression</returns> protected virtual Expression CreateDependency(Type interfaceType, ServiceRegister register, ServiceState state, string serviceName, TypeContextAttributes attributes) { //let's subcontract take responsibility to create dependency objects if (DependencyFactory == null && SharedFactory != null) { return(SharedFactory.Create(interfaceType, register, state, serviceName, attributes) ?? Expression.Default(interfaceType)); } return(DependencyFactory?.Create(interfaceType, register, state, serviceName, attributes) ?? Expression.Default(interfaceType)); }
/// <summary> /// Initializes new register for the specified interface type. /// </summary> /// <param name="interfaceType"></param> /// <param name="notifier"></param> /// <returns></returns> public ServiceRegister InitNewRegister(Type interfaceType, IServiceNotifier notifier) { _register = new ServiceRegister(); //Register self _register.Register(interfaceType); notifier.ServiceUpdateNofication += ServiceUpdateNofication; return(_register); }
private Expression GetObjectFromDependencyFactory(Type interfaceType, string factoryName, ServiceRegister registrar, ServiceState state, string mappedServiceName, TypeContextAttributes attributes) { var subcontractFactory = ServiceProviderHelper.GetDependencyFactory(DependencyFactory, factoryName); return(subcontractFactory?.Create(interfaceType, registrar, state, mappedServiceName, attributes) ?? Expression.Default(interfaceType)); }
/// <summary> /// Creates expression object for specified service type constructor. /// </summary> /// <param name="interfaceType"></param> /// <param name="serviceType"></param> /// <param name="registrar"></param> /// <param name="state"></param> /// <returns></returns> protected virtual Expression CreateConstructorExpression(Type interfaceType, Type serviceType, ServiceRegister registrar, ServiceState state) { VerifyNull(interfaceType, nameof(interfaceType)); VerifyNull(serviceType, nameof(serviceType)); VerifyNull(registrar, nameof(registrar)); VerifyNull(state, nameof(state)); ConstructorInfo[] serviceConstructors = serviceType.GetConstructors(); ConstructorInfo serviceConstructor = GetEligibleConstructorToInvoke(serviceConstructors); if (serviceConstructor != null) { Type[] reusableDependencies = GetReuseDependencies(serviceConstructor); /* Get IgnoreAttribute for the constructor, find the constructor parameters * with the specified names, if parameter name is matched then set NULL to the parameter. */ var ignoreAttribute = serviceConstructor.GetCustomAttribute <IgnoreAttribute>(); /*Get parameters of service's constructor and inject corresponding repositories values to it */ ParameterInfo[] constructorParametersInfo = serviceConstructor.GetParameters(); Expression[] arguments = new Expression[constructorParametersInfo.Length]; int index = 0; foreach (ParameterInfo constrParameter in constructorParametersInfo) { //if current parameter type is listed under reusable type, then get the expression Expression reuseDependency = GetReuseDependencyIfExists(state, constrParameter.ParameterType); if (reuseDependency != null) { arguments[index] = reuseDependency; } else { var dependencyArgument = GetDependencyObject(constrParameter, registrar, ignoreAttribute, state); //maintain state, if the parameter is listed in reusable list arguments[index] = MaintainState(reusableDependencies, state, constrParameter.ParameterType, dependencyArgument); } index++; } return(Expression.New(serviceConstructor, arguments)); } //Default constructor return(Expression.New(serviceType)); }
/// <summary> /// Create <see cref="Expression"/> for service which is associated with contract. /// </summary> /// <param name="interfaceType">Type of contract</param> /// <param name="register">The ServiceRegister</param> /// <param name="state">The ServiceState</param> /// <param name="serviceName"></param> /// <param name="attributes"></param> /// <returns>Returns <see cref="Expression"/> of service constructor.</returns> public abstract Expression Create(Type interfaceType, ServiceRegister register, ServiceState state, string serviceName, TypeContextAttributes attributes);
/// <summary> /// Creates dependency <see cref="Expression"/> object. if no dependency factory is set and shared factory exists then /// creates dependency from the shared factory; otherwise creates from the dependency factory. /// </summary> /// <param name="interfaceType">The type of the contract.</param> /// <param name="register">The service register object.</param> /// <param name="state">The service state.</param> /// <param name="serviceName"></param> /// <param name="attributes"></param> /// <returns>Dependency expression</returns> protected override Expression CreateDependency(Type interfaceType, ServiceRegister register, ServiceState state, string serviceName, TypeContextAttributes attributes) { return(Create(interfaceType, register, state, serviceName, attributes) ?? Expression.Default(interfaceType)); }