1+ using System ;
2+ using System . Collections . Generic ;
3+ using System . Linq ;
4+ using System . Reflection ;
5+ using Unity ;
6+ using Unity . Builder ;
7+ using Unity . Injection ;
8+ using Unity . Policy ;
9+ using Unity . Registration ;
10+ using Unity . Resolution ;
11+
12+ namespace LazyProxy . Unity
13+ {
14+ /// <summary>
15+ /// A class that lets you specify a factory method the container will use to create the object.
16+ /// </summary>
17+ public class UnityInjectionFactory : InjectionMember , IInjectionFactory , IBuildPlanPolicy
18+ {
19+ private static readonly FieldInfo ResolverOverrides = typeof ( BuilderContext )
20+ . GetField ( "_resolverOverrides" , BindingFlags . Instance | BindingFlags . NonPublic ) ;
21+
22+ private readonly Func < IUnityContainer , Type , string , ResolverOverride [ ] , object > _factoryFunc ;
23+
24+ /// <summary>
25+ /// Create a new instance of <see cref="UnityInjectionFactory"/> with the given factory function.
26+ /// </summary>
27+ /// <param name="factoryFunc">Factory function.</param>
28+ public UnityInjectionFactory ( Func < IUnityContainer , Type , string , ResolverOverride [ ] , object > factoryFunc )
29+ {
30+ _factoryFunc = factoryFunc ?? throw new ArgumentNullException ( nameof ( factoryFunc ) ) ;
31+ }
32+
33+ /// <summary>
34+ /// Add policies to the policies to configure the container
35+ /// to call this constructor with the appropriate parameter values.
36+ /// </summary>
37+ /// <param name="serviceType">Type of interface being registered. If no interface, this will be null.
38+ /// This parameter is ignored in this implementation.</param>
39+ /// <param name="implementationType">Type of concrete type being registered.</param>
40+ /// <param name="name">Name used to resolve the type object.</param>
41+ /// <param name="policies">Policy list to add policies to.</param>
42+ public override void AddPolicies ( Type serviceType , Type implementationType , string name , IPolicyList policies )
43+ {
44+ policies . Set ( serviceType , name , typeof ( IBuildPlanPolicy ) , this ) ;
45+ }
46+
47+ /// <summary>
48+ /// Creates an instance of this build plan's type, or fills in the existing type if passed in.
49+ /// </summary>
50+ /// <param name="context">Context used to build up the object.</param>
51+ /// <exception cref="ArgumentNullException">Context is null.</exception>
52+ public void BuildUp ( IBuilderContext context )
53+ {
54+ if ( context == null )
55+ throw new ArgumentNullException ( nameof ( context ) ) ;
56+
57+ if ( context . Existing != null )
58+ return ;
59+
60+ var resolverOverride = ResolverOverrides . GetValue ( context ) ;
61+
62+ var resolverOverrides = resolverOverride == null
63+ ? new ResolverOverride [ ] { }
64+ : ( ( IEnumerable < ResolverOverride > ) resolverOverride ) . ToArray ( ) ;
65+
66+ var container = context . Container ;
67+ var type = context . BuildKey . Type ;
68+ var name = context . BuildKey . Name ;
69+
70+ context . Existing = _factoryFunc ( container , type , name , resolverOverrides ) ;
71+ context . SetPerBuildSingleton ( ) ;
72+ }
73+ }
74+ }
0 commit comments