• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Sholtee / injector / 2251

27 Dec 2023 10:00AM UTC coverage: 90.723% (-2.0%) from 92.704%
2251

push

appveyor

Sholtee
Merge branch 'drop_opencover'

2171 of 2393 relevant lines covered (90.72%)

0.91 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

52.87
/SRC/Injector/Private/ServiceEntries/ProducibleServiceEntry.cs
1
/********************************************************************************
2
* ProducibleServiceEntry.cs                                                     *
3
*                                                                               *
4
* Author: Denes Solti                                                           *
5
********************************************************************************/
6
using System;
7
using System.Collections.Generic;
8
using System.Diagnostics;
9
using System.Linq;
10
using System.Linq.Expressions;
11
using System.Reflection;
12

13
namespace Solti.Utils.DI.Internals
14
{
15
    using Interfaces;
16
    using Primitives;
17

18
    using static Interfaces.Properties.Resources;
19
    using static Properties.Resources;
20
    using static ServiceActivator;
21

22
    /// <summary>
23
    /// Reperesents the base class of producible servce entries.
24
    /// </summary>
25
    public abstract partial class ProducibleServiceEntry : AbstractServiceEntry
26
    {
27
        #region Private
28
        private readonly List<Expression<DecoratorDelegate>> FDecorators = new();
1✔
29

30
        private static Expression<FactoryDelegate>? GetFactory(Type type, Type implementation, object? explicitArgs, ServiceOptions options)
31
        {
1✔
32
            if (!implementation.IsClass)
1✔
33
                throw new ArgumentException(NOT_A_CLASS, nameof(implementation));
×
34

35
            ConstructorInfo ctor = implementation.GetApplicableConstructor();  // validates the implementation even in case of a generic svc
1✔
36
            return !type.IsGenericTypeDefinition
1✔
37
                ? ResolveFactory(ctor, explicitArgs, options.DependencyResolvers)
1✔
38
                : null;
1✔
39
        }
1✔
40

41
        private ProducibleServiceEntry(Type type, object? key, Type? implementation, Expression<FactoryDelegate>? factory, object? explicitArgs, ServiceOptions options) : base(type, key, implementation, factory, explicitArgs, options)
1✔
42
        {
1✔
43
            if (Options!.SupportAspects)
1✔
44
            {
1✔
45
                //
46
                // Since aspects may target the implementation itself, they must be applied first
47
                //
48

49
                Debug.Assert(Decorators.Count is 0, "Aspects must be applied first");
1✔
50
                Features = ServiceEntryFeatures.SupportsAspects;
1✔
51
                if (Factory is not null)
1✔
52
                    this.ApplyAspects();
1✔
53
            }
1✔
54
        }
1✔
55
        #endregion
56

57
        #region Protected
58
        /// <summary>
59
        /// Creartes a new <see cref="ProducibleServiceEntry"/> instance.
60
        /// </summary>
61
        protected ProducibleServiceEntry(Type type, object? key, Expression<FactoryDelegate> factory, ServiceOptions options) : this
×
62
        (
×
63
            type ?? throw new ArgumentNullException(nameof(type)),
×
64
            key,
×
65
            null,
×
66
            factory ?? throw new ArgumentNullException(nameof(factory)),
×
67
            null,
×
68
            options ?? throw new ArgumentNullException(nameof(options))
×
69
        ) {}
1✔
70

71
        /// <summary>
72
        /// Creartes a new <see cref="ProducibleServiceEntry"/> instance.
73
        /// </summary>
74
        protected ProducibleServiceEntry(Type type, object? key, Type implementation, ServiceOptions options) : this
×
75
        (
×
76
            type ?? throw new ArgumentNullException(nameof(type)),
×
77
            key,
×
78
            implementation ?? throw new ArgumentNullException(nameof(implementation)),
×
79
            GetFactory
×
80
            (
×
81
                type,
×
82
                implementation,
×
83
                null,
×
84
                options ?? throw new ArgumentNullException(nameof(options))
×
85
            ),
×
86
            null,
×
87
            options
×
88
        ) {}
1✔
89

90
        /// <summary>
91
        /// Creartes a new <see cref="ProducibleServiceEntry"/> instance.
92
        /// </summary>
93
        protected ProducibleServiceEntry(Type type, object? key, Type implementation, object explicitArgs, ServiceOptions options) : this
×
94
        (
×
95
            type ?? throw new ArgumentNullException(nameof(type)),
×
96
            key,
×
97
            implementation ?? throw new ArgumentNullException(nameof(implementation)),
×
98
            GetFactory
×
99
            (
×
100
                type,
×
101
                implementation,
×
102
                explicitArgs ?? throw new ArgumentNullException(nameof(explicitArgs)),
×
103
                options ?? throw new ArgumentNullException(nameof(options))
×
104
            ),
×
105
            explicitArgs,
×
106
            options
×
107
        ) {}
1✔
108
        #endregion
109

110
        /// <inheritdoc/>
111
        public override void Build(IBuildContext context, IReadOnlyList<IFactoryVisitor> visitors)
112
        {
1✔
113
            if (context is null)
1✔
114
                throw new ArgumentNullException(nameof(context));
×
115

116
            if (visitors is null)
1✔
117
                throw new ArgumentNullException(nameof(visitors));
×
118

119
            if (Factory is null)
1✔
120
                throw new InvalidOperationException(NOT_PRODUCIBLE);
×
121

122
            //
123
            // Chain all the related delegates
124
            //
125

126
            Expression<CreateServiceDelegate> factoryExpr = (Expression<CreateServiceDelegate>) visitors.Aggregate<IFactoryVisitor, LambdaExpression>
1✔
127
            (
1✔
128
                Factory,
1✔
129
                (visited, visitor) => visitor.Visit(visited, this)
1✔
130
            );
1✔
131

132
            Debug.WriteLine($"Created factory: {Environment.NewLine}{factoryExpr.GetDebugView()}");
1✔
133
            FCreateInstance = context
1✔
134
                .Compiler
1✔
135
                .Register(factoryExpr);
1✔
136

137
            State = (State | ServiceEntryStates.Built) & ~ServiceEntryStates.Validated;
1✔
138
        }
1✔
139

140
        /// <inheritdoc/>
141
        public sealed override void UpdateState(ServiceEntryStates newState)
142
        {
1✔
143
            Debug.WriteLineIf(newState < State, $"Downgrading state of {this}");
1✔
144
            UpdateStateInternal(newState);
1✔
145
        }
1✔
146

147
        /// <inheritdoc/>
148
        public override ServiceEntryFeatures Features { get; }
1✔
149

150
        /// <inheritdoc/>
151
        public override void Decorate(Expression<DecoratorDelegate> decorator)
152
        {
1✔
153
            if (Factory is null)
1✔
154
                throw new NotSupportedException(DECORATING_NOT_SUPPORTED);
1✔
155

156
            FDecorators.Add(decorator ?? throw new ArgumentNullException(nameof(decorator)));
×
157
        }
1✔
158

159
        /// <summary>
160
        /// Bound decorators.
161
        /// </summary>
162
        public sealed override IReadOnlyList<Expression<DecoratorDelegate>> Decorators => FDecorators;
1✔
163
    }
164
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc