/// <summary> /// Constructor. Creates a new TypeRegistrationProvider instance. /// </summary> /// <param name="container">SimpleInjector Container instance</param> /// <param name="options">Registration options to use to auto-register types.</param> public TypeRegistrationProvider(Container container, IAutoRegistrationOptions options) { this.container = container; this.options = options; this.container.Options.AllowOverridingRegistrations = true; }
/// <summary> /// Discovers any Func dependencies of the specified type and attempts to register them. /// </summary> /// <param name="concreteType">Concrete type for which the dependencies should be discovered /// and registered</param> /// <param name="container">SimpleInjector container in which the dependencies should be registered.</param> /// <param name="options">Options to apply to the discovery and registration process.</param> public void RegisterDependencies(Type concreteType, Container container, IAutoRegistrationOptions options) { foreach (var ctor in concreteType.GetConstructors().Where((x) => x.IsPublic)) { foreach (var param in ctor.GetParameters().Where((x) => x.ParameterType.Name.StartsWith("Func`"))) { var funcParamType = param.ParameterType; var genericArgType = funcParamType.GenericTypeArguments.FirstOrDefault(); if (genericArgType != null && genericArgType.IsInterface && options.AutoRegistrationEnabledProvider.IsAutoRegistrationEnabled(genericArgType)) { //Since Funcs<> do not retain any state and the wrapped Func<> accounts for the //lifestyle of the object, it can always be made singleton, while the wrapped //type may be transient. container.RegisterSingle(funcParamType, () => { //Create a Func<> with the container in context to create an instance of the type var method = typeof(ContextualFuncCreationHelper).GetMethod("GetFunc").MakeGenericMethod(genericArgType); var funcInstance = new ContextualFuncCreationHelper(container); return Delegate.CreateDelegate(funcParamType, funcInstance, method); }); } } } }
/// <summary> /// Discovers any Lazy dependencies of the specified type and attempts to register them. /// </summary> /// <param name="concreteType">Concrete type for which the dependencies should be discovered /// and registered</param> /// <param name="container">SimpleInjector container in which the dependencies should be registered.</param> /// <param name="options">Options to apply to the discovery and registration process.</param> public void RegisterDependencies(Type concreteType, Container container, IAutoRegistrationOptions options) { foreach (var ctor in concreteType.GetConstructors().Where((x) => x.IsPublic)) { foreach (var param in ctor.GetParameters().Where((x) => x.ParameterType.Name.StartsWith("Lazy`"))) { var funcParamType = param.ParameterType; var genericArgType = funcParamType.GenericTypeArguments.FirstOrDefault(); if (genericArgType != null && genericArgType.IsInterface && options.AutoRegistrationEnabledProvider.IsAutoRegistrationEnabled(genericArgType)) { Lifestyle lifestyle = options.LifestyleResolver.GetLifestyle(genericArgType); if (lifestyle == null) { throw new Exception(string.Format("Lifestyle not defined for wrapped type of Lazy<{0}>", genericArgType.Name)); } Func<object> creationDelegate = () => { //First create a Func<> with the container in context to create an instance of the type var method = typeof(ContextualFuncCreationHelper).GetMethod("GetFunc").MakeGenericMethod(genericArgType); var funcType = typeof(Func<>).MakeGenericType(genericArgType); var funcInstance = new ContextualFuncCreationHelper(container); var dgt = Delegate.CreateDelegate(funcType, funcInstance, method); //Create lazy with the Func delegate as a parameter return Activator.CreateInstance(funcParamType, dgt); }; //Since the Lazy<> acts as a singleton and retains state, we need to determine if the Lazy<> //should be transient or singleton if (lifestyle == Lifestyle.Singleton) { container.RegisterSingle(funcParamType, creationDelegate); } else { container.Register(funcParamType, creationDelegate); } } } } }
/// <summary> /// Discovers any IEnumerable dependencies of the specified type and attempts to register them. /// </summary> /// <param name="concreteType">Concrete type for which the dependencies should be discovered /// and registered</param> /// <param name="container">SimpleInjector container in which the dependencies should be registered.</param> /// <param name="options">Options to apply to the discovery and registration process.</param> public void RegisterDependencies(Type concreteType, Container container, IAutoRegistrationOptions options) { foreach (var ctor in concreteType.GetConstructors().Where((x) => x.IsPublic)) { foreach (var param in ctor.GetParameters().Where((x) => typeof(System.Collections.IEnumerable).IsAssignableFrom(x.ParameterType))) { var genericArgType = param.ParameterType.GenericTypeArguments.FirstOrDefault(); if (genericArgType != null && genericArgType.IsInterface && options.AutoRegistrationEnabledProvider.IsAutoRegistrationEnabled(genericArgType)) { container.RegisterAll(genericArgType, options.ImplementationProvider.GetConcreteImplementionsOf(genericArgType)); } } } }
/// <summary> /// Discovers and registers all types within the root namespace of the application. To extend the behavior or specify /// details, including the root namespace, please specify the options object. /// </summary> /// <param name="container">SimpleInjector container in which these types should be registered.</param> /// <param name="options">Optional: options to use while registering types. This can also be used or override or /// extend the behavior of the auto-registration process.</param> public static void AutoRegister(this Container container, IAutoRegistrationOptions options = null) { if (options == null) { string ns = null; //Must be in constructor to get actual calling assembly var workingAssembly = Assembly.GetEntryAssembly() ?? Assembly.GetCallingAssembly(); if (workingAssembly != null) { var workingNamespace = workingAssembly.FullName; var rootNamespaceDotIndex = workingNamespace.IndexOf("."); ns = rootNamespaceDotIndex > 0 ? workingNamespace.Substring(0, rootNamespaceDotIndex) : workingNamespace; } options = new AutoRegistrationOptions(ns); } var typeRegProvider = new TypeRegistrationProvider(container, options); typeRegProvider.RegisterTypes(); }