Diff of /Implementation/APUnitTestFramework/ComponentModelImplementation.cs [000000] .. [5a4bff]  Maximize  Restore

Switch to unified view

a b/Implementation/APUnitTestFramework/ComponentModelImplementation.cs
1
using _3S.CoDeSys.Core.ComponentModel;
2
using _3S.CoDeSys.Core.Components;
3
using _3S.CoDeSys.Core.Views;
4
using System;
5
using System.Collections.Generic;
6
using System.Diagnostics;
7
using System.Linq;
8
using System.Reflection;
9
using System.Xml;
10
11
namespace _3S.APUnitTestFramework
12
{
13
    [TypeGuid("{638AA04C-726D-4CD1-99EE-CE402D0DD566}")]
14
    public class ComponentModelImplementation : IComponentModelImplementationForUnitTest
15
    {
16
        public IDependencyResolveContext CreateDependencyResolveContext(Profile profile)
17
        {
18
            // Not required for unit testing.
19
            throw new NotImplementedException();
20
        }
21
22
        public IEnumerable<IDependency> GetDependencies(Guid plugInGuid, Version version, bool inproc)
23
        {
24
            // Not required for unit testing.
25
            throw new NotImplementedException();
26
        }
27
28
        public void InjectDependencies(IDependencyInjectable injectable, Type callingType)
29
        {
30
            if (injectable == null)
31
                throw new ArgumentNullException(nameof(injectable));
32
            if (_dependencyResolver == null)
33
                throw new InvalidOperationException("No dependency resolver has been set.");
34
35
            var type = injectable.GetType();
36
            foreach (var target in _injectionTargetCache.GetInjectionTargets(type))
37
            {
38
                var value = target.GetInjectionValue(callingType);
39
                value.Prepare(target.Member, _dependencyResolver);
40
                target.Assign(injectable, value);
41
            }
42
43
            injectable.InjectionComplete();
44
        }
45
46
        public IDependency LoadDependency(XmlElement element)
47
        {
48
            // Not required for unit testing.
49
            throw new NotImplementedException();
50
        }
51
52
        public DependencyResolveResult ResolveDependency(SpecificDependency specificDependency, IDependencyResolveContext context)
53
        {
54
            // Not required for unit testing.
55
            throw new NotImplementedException();
56
        }
57
58
        public DependencyResolveResult ResolveDependency(MultipleDependency multipleDependency, IDependencyResolveContext context)
59
        {
60
            // Not required for unit testing.
61
            throw new NotImplementedException();
62
        }
63
64
        public DependencyResolveResult ResolveDependency(SingleDependency singleDependency, IDependencyResolveContext context)
65
        {
66
            // Not required for unit testing.
67
            throw new NotImplementedException();
68
        }
69
70
        public void Save(SpecificDependency specificDependency, XmlElement parentElement)
71
        {
72
            // Not required for unit testing.
73
            throw new NotImplementedException();
74
        }
75
76
        public void Save(MultipleDependency multipleDependency, XmlElement parentElement)
77
        {
78
            // Not required for unit testing.
79
            throw new NotImplementedException();
80
        }
81
82
        public void SaveDependency(SingleDependency singleDependency, XmlElement parentElement)
83
        {
84
            // Not required for unit testing.
85
            throw new NotImplementedException();
86
        }
87
88
        public void SetupForUnitTest(Testbed testbed, string profileName, Profile profile)
89
        {
90
            _dependencyResolver = new DependencyResolver(testbed, profileName, profile);
91
        }
92
93
        private InjectionTargetCache _injectionTargetCache = new InjectionTargetCache();
94
        private DependencyResolver _dependencyResolver;
95
    }
96
97
    class InjectionTargetCache
98
    {
99
        public IEnumerable<AbstractInjectionTarget> GetInjectionTargets(Type type)
100
        {
101
            IEnumerable<AbstractInjectionTarget> result;
102
            _dictionary.TryGetValue(type, out result);
103
            if (result == null)
104
            {
105
                result = GetInjectionTargetsByReflection(type);
106
                _dictionary[type] = result;
107
            }
108
            return result;
109
        }
110
111
        private static IEnumerable<AbstractInjectionTarget> GetInjectionTargetsByReflection(Type type)
112
        {
113
            var result = new List<AbstractInjectionTarget>();
114
115
            IEnumerable<MemberInfo> properties = type.GetProperties();
116
            IEnumerable<MemberInfo> fields = type.GetFields();
117
            foreach (var member in Enumerable.Concat(properties, fields))
118
            {
119
                var target = AbstractInjectionTarget.CreateFromMember(member);
120
                if (target != null)
121
                    result.Add(target);
122
            }
123
124
            return result;
125
        }
126
127
        private Dictionary<Type, IEnumerable<AbstractInjectionTarget>> _dictionary = new Dictionary<Type, IEnumerable<AbstractInjectionTarget>>();
128
    }
129
130
    abstract class AbstractInjectionTarget
131
    {
132
        public MemberInfo Member { get; private set; }
133
        private IInjectionValue _injectionValue;
134
135
        protected AbstractInjectionTarget(MemberInfo member)
136
        {
137
            if (member == null)
138
                throw new ArgumentNullException(nameof(member));
139
140
            Member = member;
141
        }
142
143
        public static AbstractInjectionTarget CreateFromMember(MemberInfo member)
144
        {
145
            var attr = Attribute.GetCustomAttribute(member, typeof(AbstractInjectAttribute), false);
146
            if (attr == null)
147
            {
148
                return null;
149
            }
150
            else if (attr is InjectSingleInstanceAttribute)
151
            {
152
                var shared = ((InjectSingleInstanceAttribute)attr).Shared;
153
                var optional = ((InjectSingleInstanceAttribute)attr).Optional;
154
                return new SingleInstanceInjectionTarget(shared, optional, member);
155
            }
156
            else if (attr is InjectMultipleInstancesAttribute)
157
            {
158
                var shared = ((InjectMultipleInstancesAttribute)attr).Shared;
159
                var optional = ((InjectMultipleInstancesAttribute)attr).Optional;
160
                return new MultipleInstancesInjectionTarget(shared, optional, member);
161
            }
162
            else if (attr is InjectSpecificInstanceAttribute)
163
            {
164
                var typeGuid = ((InjectSpecificInstanceAttribute)attr).TypeGuid;
165
                var shared = ((InjectSpecificInstanceAttribute)attr).Shared;
166
                var optional = ((InjectSpecificInstanceAttribute)attr).Optional;
167
                return new SpecificInstanceInjectionTarget(typeGuid, shared, optional, member);
168
            }
169
            else if (attr is InjectAnyInstanceAttribute)
170
            {
171
                return new AnyInstanceInjectionTarget(member);
172
            }
173
            else if (attr is InjectSpecificTypeInformationAttribute)
174
            {
175
                var typeGuid = ((InjectSpecificTypeInformationAttribute)attr).TypeGuid;
176
                var optional = ((InjectSpecificTypeInformationAttribute)attr).Optional;
177
                return new SpecificTypeInformationInjectionTarget(typeGuid, optional, member);
178
            }
179
            else if (attr is InjectAnyTypeInformationAttribute)
180
            {
181
                return new AnyTypeInformationInjectionTarget(member);
182
            }
183
            else if (attr is InjectActiveProfileAttribute)
184
            {
185
                return new ActiveProfileInjectionTarget(member);
186
            }
187
            else if (attr is InjectFrameFormAttribute)
188
            {
189
                return new FrameFormInjectionTarget(member);
190
            }
191
            else
192
            {
193
                return null;
194
            }
195
        }
196
197
        public IInjectionValue GetInjectionValue(Type callingType)
198
        {
199
            if (_injectionValue == null)
200
                _injectionValue = DoGetInjectionValue(callingType);
201
202
            return _injectionValue;
203
        }
204
205
        protected abstract IInjectionValue DoGetInjectionValue(Type callingType);
206
207
        public void Assign(IDependencyInjectable injectable, IInjectionValue value)
208
        {
209
            var field = Member as FieldInfo;
210
            var property = Member as PropertyInfo;
211
212
            if (field != null)
213
                field.SetValue(injectable, value);
214
            else if (property != null)
215
                property.SetValue(injectable, value, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, null, null);
216
            else
217
                Debug.Fail("Injection target must be a field or property.");
218
        }
219
220
        protected Type MemberType
221
        {
222
            get
223
            {
224
                var field = Member as FieldInfo;
225
                var property = Member as PropertyInfo;
226
227
                if (field != null)
228
                    return field.FieldType;
229
                else if (property != null)
230
                    return property.PropertyType;
231
                else
232
                    return null;
233
            }
234
        }
235
236
        protected static bool IsOfGenericType(Type memberType, Type genericType)
237
        {
238
            if (!memberType.IsGenericType)
239
                return false;
240
            else if (!genericType.IsAssignableFrom(memberType.GetGenericTypeDefinition()))
241
                return false;
242
            else
243
                return true;
244
        }
245
    }
246
247
    class SingleInstanceInjectionTarget : AbstractInjectionTarget
248
    {
249
        public SingleInstanceInjectionTarget(bool shared, bool optional, MemberInfo member)
250
            : base(member)
251
        {
252
            _shared = shared;
253
            _optional = optional;
254
        }
255
256
        protected override IInjectionValue DoGetInjectionValue(Type callingType)
257
        {
258
            Type type;
259
260
            if (_shared)
261
            {
262
                if (!IsOfGenericType(MemberType, typeof(ISharedSingleInstanceProvider<>)))
263
                    throw new WrongMemberTypeForInjectionException(Member, typeof(ISharedSingleInstanceProvider<>));
264
265
                var contractType = Enumerable.First(MemberType.GetGenericArguments());
266
                type = _optional ? typeof(OptionalSharedSingleInstanceProvider<>).MakeGenericType(contractType) : typeof(SharedSingleInstanceProvider<>).MakeGenericType(contractType);
267
            }
268
            else
269
            {
270
                if (!IsOfGenericType(MemberType, typeof(ISingleInstanceProvider<>)))
271
                    throw new WrongMemberTypeForInjectionException(Member, typeof(ISingleInstanceProvider<>));
272
273
                var contractType = Enumerable.First(MemberType.GetGenericArguments());
274
                type = _optional ? typeof(OptionalSingleInstanceProvider<>).MakeGenericType(contractType) : typeof(SingleInstanceProvider<>).MakeGenericType(contractType);
275
            }
276
277
            return (IInjectionValue)Activator.CreateInstance(type);
278
        }
279
280
        private bool _shared;
281
        private bool _optional;
282
    }
283
284
    class MultipleInstancesInjectionTarget : AbstractInjectionTarget
285
    {
286
        public MultipleInstancesInjectionTarget(bool shared, bool optional, MemberInfo member)
287
            : base(member)
288
        {
289
            _shared = shared;
290
            _optional = optional;
291
        }
292
293
        protected override IInjectionValue DoGetInjectionValue(Type callingType)
294
        {
295
            Type type;
296
297
            if (_shared)
298
            {
299
                if (!IsOfGenericType(MemberType, typeof(ISharedMultipleInstancesProvider<>)))
300
                    throw new WrongMemberTypeForInjectionException(Member, typeof(ISharedMultipleInstancesProvider<>));
301
302
                var contractType = Enumerable.First(MemberType.GetGenericArguments());
303
                type = _optional ? typeof(OptionalSharedMultipleInstancesProvider<>).MakeGenericType(contractType) : typeof(SharedMultipleInstancesProvider<>).MakeGenericType(contractType);
304
            }
305
            else
306
            {
307
                if (!IsOfGenericType(MemberType, typeof(IMultipleInstancesProvider<>)))
308
                    throw new WrongMemberTypeForInjectionException(Member, typeof(IMultipleInstancesProvider<>));
309
310
                var contractType = Enumerable.First(MemberType.GetGenericArguments());
311
                type = _optional ? typeof(OptionalMultipleInstancesProvider<>).MakeGenericType(contractType) : typeof(MultipleInstancesProvider<>).MakeGenericType(contractType);
312
            }
313
314
            return (IInjectionValue)Activator.CreateInstance(type);
315
        }
316
317
        private bool _shared;
318
        private bool _optional;
319
    }
320
321
    class SpecificInstanceInjectionTarget : AbstractInjectionTarget
322
    {
323
        public SpecificInstanceInjectionTarget(Guid typeGuid, bool shared, bool optional, MemberInfo member)
324
            : base(member)
325
        {
326
            _typeGuid = typeGuid;
327
            _shared = shared;
328
            _optional = optional;
329
        }
330
331
        protected override IInjectionValue DoGetInjectionValue(Type callingType)
332
        {
333
            Type type;
334
335
            if (_shared)
336
            {
337
                if (!IsOfGenericType(MemberType, typeof(ISharedSingleInstanceProvider<>)))
338
                    throw new WrongMemberTypeForInjectionException(Member, typeof(ISharedSingleInstanceProvider<>));
339
340
                var contractType = Enumerable.First(MemberType.GetGenericArguments());
341
                type = _optional ? typeof(OptionalSharedSpecificInstanceProvider<>).MakeGenericType(contractType) : typeof(SharedSpecificInstanceProvider<>).MakeGenericType(contractType);
342
            }
343
            else
344
            {
345
                if (!IsOfGenericType(MemberType, typeof(ISingleInstanceProvider<>)))
346
                    throw new WrongMemberTypeForInjectionException(Member, typeof(ISingleInstanceProvider<>));
347
348
                var contractType = Enumerable.First(MemberType.GetGenericArguments());
349
                type = _optional ? typeof(OptionalSpecificInstanceProvider<>).MakeGenericType(contractType) : typeof(SpecificInstanceProviderFallback<>).MakeGenericType(contractType);
350
            }
351
352
            var args = new object[] { _typeGuid };
353
            return (IInjectionValue)Activator.CreateInstance(type, args);
354
        }
355
356
        private Guid _typeGuid;
357
        private bool _shared;
358
        private bool _optional;
359
    }
360
361
    class AnyInstanceInjectionTarget : AbstractInjectionTarget
362
    {
363
        public AnyInstanceInjectionTarget(MemberInfo member)
364
            : base(member)
365
        {
366
        }
367
368
        protected override IInjectionValue DoGetInjectionValue(Type callingType)
369
        {
370
            if (!IsOfGenericType(MemberType, typeof(IAnyInstanceProvider<>)))
371
                throw new WrongMemberTypeForInjectionException(Member, typeof(IAnyInstanceProvider<>));
372
373
            var contractType = Enumerable.First(MemberType.GetGenericArguments());
374
            var type = typeof(AnyInstanceProvider<>).MakeGenericType(contractType);
375
            return (IInjectionValue)Activator.CreateInstance(type);
376
        }
377
    }
378
379
    class SpecificTypeInformationInjectionTarget : AbstractInjectionTarget
380
    {
381
        public SpecificTypeInformationInjectionTarget(Guid typeGuid, bool optional, MemberInfo member)
382
            : base(member)
383
        {
384
            _typeGuid = typeGuid;
385
            _optional = optional;
386
        }
387
388
        protected override IInjectionValue DoGetInjectionValue(Type callingType)
389
        {
390
            if (!typeof(ISpecificTypeInformation).IsAssignableFrom(MemberType))
391
                throw new WrongMemberTypeForInjectionException(Member, typeof(ISpecificTypeInformation));
392
393
            if (_optional)
394
                return new OptionalSpecificTypeInformation(_typeGuid);
395
            else
396
                return new SpecificTypeInformation(_typeGuid);
397
        }
398
399
        private Guid _typeGuid;
400
        private bool _optional;
401
    }
402
403
    class AnyTypeInformationInjectionTarget : AbstractInjectionTarget
404
    {
405
        public AnyTypeInformationInjectionTarget(MemberInfo member)
406
            : base(member)
407
        {
408
        }
409
410
        protected override IInjectionValue DoGetInjectionValue(Type callingType)
411
        {
412
            if (!typeof(IAnyTypeInformation).IsAssignableFrom(MemberType))
413
                throw new WrongMemberTypeForInjectionException(Member, typeof(IAnyTypeInformation));
414
415
            return new AnyTypeInformation();
416
        }
417
    }
418
419
    class ActiveProfileInjectionTarget : AbstractInjectionTarget
420
    {
421
        public ActiveProfileInjectionTarget(MemberInfo member)
422
            : base(member)
423
        {
424
        }
425
426
        protected override IInjectionValue DoGetInjectionValue(Type callingType)
427
        {
428
            if (!typeof(IProfileInformation).IsAssignableFrom(MemberType))
429
                throw new WrongMemberTypeForInjectionException(Member, typeof(IProfileInformation));
430
431
            return new ProfileInformation();
432
        }
433
    }
434
435
    class FrameFormInjectionTarget : AbstractInjectionTarget
436
    {
437
        public FrameFormInjectionTarget(MemberInfo member)
438
            : base(member)
439
        {
440
        }
441
442
        protected override IInjectionValue DoGetInjectionValue(Type callingType)
443
        {
444
            if (!typeof(IWinFormWrapperProxy).IsAssignableFrom(MemberType))
445
                throw new WrongMemberTypeForInjectionException(Member, typeof(IWinFormWrapperProxy));
446
447
            return new WinFormWrapperProxy();
448
        }
449
    }
450
451
    interface IInjectionValue
452
    {
453
        void Prepare(MemberInfo member, DependencyResolver dependencyResolver);
454
    }
455
456
    abstract class AbstractSingleInstanceProvider<TContract> : IInjectionValue where TContract : class
457
    {
458
        public abstract void Prepare(MemberInfo member, DependencyResolver dependencyResolver);
459
460
        public Guid TypeGuid
461
        {
462
            get { return _valueProvider.TypeGuid; }
463
        }
464
465
        protected void DoPrepare(MemberInfo member, bool optional, DependencyResolver dependencyResolver)
466
        {
467
            if (dependencyResolver == null)
468
                throw new ArgumentNullException(nameof(dependencyResolver));
469
470
            _valueProvider = dependencyResolver.ResolveSingle(typeof(TContract), optional, member);
471
        }
472
473
        protected TContract DoCreate()
474
        {
475
            return _valueProvider.CreateInstance<TContract>();
476
        }
477
478
        private IValueProvider _valueProvider;
479
    }
480
481
    abstract class AbstractSharedSingleInstanceProvider<TContract> : AbstractSingleInstanceProvider<TContract>, ISharedSingleInstanceProvider<TContract> where TContract : class
482
    {
483
        public TContract Value
484
        {
485
            get
486
            {
487
                if (!_valueCreated)
488
                {
489
                    _value = DoCreate();
490
                    _valueCreated = true;
491
                }
492
                return _value;
493
            }
494
        }
495
496
        private TContract _value;
497
        private bool _valueCreated;
498
    }
499
500
    class SingleInstanceProvider<TContract> : AbstractSingleInstanceProvider<TContract>, ISingleInstanceProvider<TContract> where TContract : class
501
    {
502
        public override void Prepare(MemberInfo member, DependencyResolver depencencyResolver)
503
        {
504
            DoPrepare(member, false, depencencyResolver);
505
        }
506
507
        public TContract Create()
508
        {
509
            return DoCreate();
510
        }
511
    }
512
513
    class OptionalSingleInstanceProvider<TContract> : AbstractSingleInstanceProvider<TContract>, ISingleInstanceProvider<TContract> where TContract : class
514
    {
515
        public override void Prepare(MemberInfo member, DependencyResolver depencencyResolver)
516
        {
517
            DoPrepare(member, true, depencencyResolver);
518
        }
519
520
        public TContract Create()
521
        {
522
            return DoCreate();
523
        }
524
    }
525
526
    class SharedSingleInstanceProvider<TContract> : AbstractSharedSingleInstanceProvider<TContract> where TContract : class
527
    {
528
        public override void Prepare(MemberInfo member, DependencyResolver depencencyResolver)
529
        {
530
            DoPrepare(member, false, depencencyResolver);
531
        }
532
    }
533
534
    class OptionalSharedSingleInstanceProvider<TContract> : AbstractSharedSingleInstanceProvider<TContract> where TContract : class
535
    {
536
        public override void Prepare(MemberInfo member, DependencyResolver depencencyResolver)
537
        {
538
            DoPrepare(member, true, depencencyResolver);
539
        }
540
    }
541
542
    abstract class AbstractMultipleInstancesProvider<TContract> : IInjectionValue where TContract : class
543
    {
544
        public abstract void Prepare(MemberInfo member, DependencyResolver depencencyResolver);
545
546
        public IEnumerable<Guid> TypeGuids
547
        {
548
            get { return _valueProviders.Select(vp => vp.TypeGuid); }
549
        }
550
551
        protected void DoPrepare(MemberInfo member, bool optional, DependencyResolver dependencyResolver)
552
        {
553
            if (dependencyResolver == null)
554
                throw new ArgumentNullException(nameof(dependencyResolver));
555
556
            _valueProviders = dependencyResolver.ResolveMultiple(typeof(TContract), optional, member);
557
        }
558
559
        protected IEnumerable<TContract> DoCreate()
560
        {
561
            return _valueProviders.Select(vp => vp.CreateInstance<TContract>());
562
        }
563
564
        private IEnumerable<IValueProvider> _valueProviders;
565
    }
566
567
    abstract class AbstractSharedMultipleInstancesProvider<TContract> : AbstractMultipleInstancesProvider<TContract>, ISharedMultipleInstancesProvider<TContract> where TContract : class
568
    {
569
        public IEnumerable<TContract> Value
570
        {
571
            get
572
            {
573
                if (!_valueCreated)
574
                {
575
                    _value = Enumerable.ToList(DoCreate());
576
                    _valueCreated = true;
577
                }
578
                return _value;
579
            }
580
        }
581
582
        private List<TContract> _value;
583
        private bool _valueCreated;
584
    }
585
586
    class MultipleInstancesProvider<TContract> : AbstractMultipleInstancesProvider<TContract>, IMultipleInstancesProvider<TContract> where TContract : class
587
    {
588
        public override void Prepare(MemberInfo member, DependencyResolver depencencyResolver)
589
        {
590
            DoPrepare(member, false, depencencyResolver);
591
        }
592
593
        public IEnumerable<TContract> Create()
594
        {
595
            return Enumerable.ToList(DoCreate()); // If we would not call ToList(), every iteration over the enumerable would create new objects, which is likely not expected by the caller.
596
        }
597
598
        public TContract CreateFirst()
599
        {
600
            return Enumerable.First(DoCreate());
601
        }
602
    }
603
604
    class OptionalMultipleInstancesProvider<TContract> : AbstractMultipleInstancesProvider<TContract>, IMultipleInstancesProvider<TContract> where TContract : class
605
    {
606
        public override void Prepare(MemberInfo member, DependencyResolver depencencyResolver)
607
        {
608
            DoPrepare(member, true, depencencyResolver);
609
        }
610
611
        public IEnumerable<TContract> Create()
612
        {
613
            return Enumerable.ToList(DoCreate()); // If we would not call ToList(), every iteration over the enumerable would create new objects, which is likely not expected by the caller.
614
        }
615
616
        public TContract CreateFirst()
617
        {
618
            return Enumerable.FirstOrDefault(DoCreate());
619
        }
620
    }
621
622
    class SharedMultipleInstancesProvider<TContract> : AbstractSharedMultipleInstancesProvider<TContract> where TContract : class
623
    {
624
        public override void Prepare(MemberInfo member, DependencyResolver depencencyResolver)
625
        {
626
            DoPrepare(member, false, depencencyResolver);
627
        }
628
    }
629
630
    class OptionalSharedMultipleInstancesProvider<TContract> : AbstractSharedMultipleInstancesProvider<TContract> where TContract : class
631
    {
632
        public override void Prepare(MemberInfo member, DependencyResolver depencencyResolver)
633
        {
634
            DoPrepare(member, true, depencencyResolver);
635
        }
636
    }
637
638
    abstract class AbstractSpecificInstanceProvider<TContract> : IInjectionValue where TContract : class
639
    {
640
        protected AbstractSpecificInstanceProvider(Guid typeGuid)
641
        {
642
            _typeGuid = typeGuid;
643
        }
644
645
        public Guid TypeGuid
646
        {
647
            get { return _valueProvider.TypeGuid; }
648
        }
649
650
        public abstract void Prepare(MemberInfo member, DependencyResolver depencencyResolver);
651
652
        protected void DoPrepare(MemberInfo member, bool optional, DependencyResolver dependencyResolver)
653
        {
654
            if (dependencyResolver == null)
655
                throw new ArgumentNullException(nameof(dependencyResolver));
656
657
            _valueProvider = dependencyResolver.ResolveSpecific(_typeGuid, typeof(TContract), optional, member);
658
        }
659
660
        protected TContract DoCreate()
661
        {
662
            return _valueProvider.CreateInstance<TContract>();
663
        }
664
665
        private Guid _typeGuid;
666
        private IValueProvider _valueProvider;
667
    }
668
669
    abstract class AbstractSharedSpecificInstanceProvider<TContract> : AbstractSpecificInstanceProvider<TContract>, ISharedSingleInstanceProvider<TContract> where TContract : class
670
    {
671
        protected AbstractSharedSpecificInstanceProvider(Guid typeGuid)
672
            : base(typeGuid)
673
        {
674
        }
675
676
        public TContract Value
677
        {
678
            get
679
            {
680
                if (!_valueCreated)
681
                {
682
                    _value = DoCreate();
683
                    _valueCreated = true;
684
                }
685
                return _value;
686
            }
687
        }
688
689
        private TContract _value;
690
        private bool _valueCreated;
691
    }
692
693
    class SpecificInstanceProviderFallback<TContract> : AbstractSpecificInstanceProvider<TContract>, ISingleInstanceProvider<TContract> where TContract : class
694
    {
695
        public SpecificInstanceProviderFallback(Guid typeGuid)
696
            : base(typeGuid)
697
        {
698
        }
699
700
        public override void Prepare(MemberInfo member, DependencyResolver depencencyResolver)
701
        {
702
            DoPrepare(member, false, depencencyResolver);
703
        }
704
705
        public TContract Create()
706
        {
707
            return DoCreate();
708
        }
709
    }
710
711
    class OptionalSpecificInstanceProvider<TContract> : AbstractSpecificInstanceProvider<TContract>, ISingleInstanceProvider<TContract> where TContract : class
712
    {
713
        public OptionalSpecificInstanceProvider(Guid typeGuid)
714
            : base(typeGuid)
715
        {
716
        }
717
718
        public override void Prepare(MemberInfo member, DependencyResolver depencencyResolver)
719
        {
720
            DoPrepare(member, true, depencencyResolver);
721
        }
722
723
        public TContract Create()
724
        {
725
            return DoCreate();
726
        }
727
    }
728
729
    class SharedSpecificInstanceProvider<TContract> : AbstractSharedSpecificInstanceProvider<TContract> where TContract : class
730
    {
731
        public SharedSpecificInstanceProvider(Guid typeGuid)
732
            : base(typeGuid)
733
        {
734
        }
735
736
        public override void Prepare(MemberInfo member, DependencyResolver depencencyResolver)
737
        {
738
            DoPrepare(member, false, depencencyResolver);
739
        }
740
    }
741
742
    class OptionalSharedSpecificInstanceProvider<TContract> : AbstractSharedSpecificInstanceProvider<TContract> where TContract : class
743
    {
744
        public OptionalSharedSpecificInstanceProvider(Guid typeGuid)
745
            : base(typeGuid)
746
        {
747
        }
748
749
        public override void Prepare(MemberInfo member, DependencyResolver depencencyResolver)
750
        {
751
            DoPrepare(member, true, depencencyResolver);
752
        }
753
    }
754
755
    class AnyInstanceProvider<TContract> : IAnyInstanceProvider<TContract>, IInjectionValue where TContract : class
756
    {
757
        public void Prepare(MemberInfo member, DependencyResolver depencencyResolver)
758
        {
759
            _member = member;
760
            _dependencyResolver = depencencyResolver;
761
        }
762
763
        public TContract Create(Guid typeGuid)
764
        {
765
            if (_dependencyResolver == null)
766
                throw new InvalidOperationException("The dependency resolver has not been set.");
767
768
            return _dependencyResolver.ResolveSpecific(typeGuid, typeof(TContract), false, _member).CreateInstance<TContract>();
769
        }
770
771
        public TContract TryCreate(Guid typeGuid)
772
        {
773
            if (_dependencyResolver == null)
774
                throw new InvalidOperationException("The dependency resolver has not been set.");
775
776
            return _dependencyResolver.ResolveSpecific(typeGuid, typeof(TContract), true, _member).CreateInstance<TContract>();
777
        }
778
779
        private MemberInfo _member;
780
        private DependencyResolver _dependencyResolver;
781
    }
782
783
    abstract class AbstractSpecificTypeInformation : ISpecificTypeInformation, IInjectionValue
784
    {
785
        protected AbstractSpecificTypeInformation(Guid typeGuid)
786
        {
787
            TypeGuid = typeGuid;
788
        }
789
790
        public abstract void Prepare(MemberInfo member, DependencyResolver depencencyResolver);
791
792
        public Guid TypeGuid { get; private set; }
793
794
        public Type Type { get; private set; }
795
        public TypeInformation TypeInformation { get; private set; }
796
797
        protected void DoPrepare(MemberInfo member, bool optional, DependencyResolver dependencyResolver)
798
        {
799
            if (dependencyResolver == null)
800
                throw new ArgumentNullException(nameof(dependencyResolver));
801
802
            try
803
            {
804
                var valueProvider = dependencyResolver.ResolveSpecific(TypeGuid, typeof(object), optional, member);
805
                Type = valueProvider.Type;
806
                TypeInformation = valueProvider.TypeInformation;
807
            }
808
            catch (NoInstanceForInjectionException ex)
809
            {
810
                // It is inconsistent compared to other injection to throw the exception
811
                // immediately within the DoPrepare() method (instead upon value retrieval by the
812
                // consumer), but the original implementation behaves likewise.
813
                throw new NoTypeInformationForInjectionException(ex.InjectionTarget);
814
            }
815
        }
816
    }
817
818
    class SpecificTypeInformation : AbstractSpecificTypeInformation
819
    {
820
        public SpecificTypeInformation(Guid typeGuid)
821
            : base(typeGuid)
822
        {
823
        }
824
825
        public override void Prepare(MemberInfo member, DependencyResolver depencencyResolver)
826
        {
827
            DoPrepare(member, false, depencencyResolver);
828
        }
829
    }
830
831
    class OptionalSpecificTypeInformation : AbstractSpecificTypeInformation
832
    {
833
        public OptionalSpecificTypeInformation(Guid typeGuid)
834
            : base(typeGuid)
835
        {
836
        }
837
838
        public override void Prepare(MemberInfo member, DependencyResolver depencencyResolver)
839
        {
840
            DoPrepare(member, true, depencencyResolver);
841
        }
842
    }
843
844
    class AnyTypeInformation : IAnyTypeInformation, IInjectionValue
845
    {
846
        public void Prepare(MemberInfo member, DependencyResolver depencencyResolver)
847
        {
848
            _member = member;
849
            _dependencyResolver = depencencyResolver;
850
        }
851
852
        public Type GetType(Guid typeGuid)
853
        {
854
            if (_dependencyResolver == null)
855
                throw new ArgumentNullException(nameof(_dependencyResolver));
856
857
            return _dependencyResolver.ResolveSpecific(typeGuid, typeof(object), false, _member).Type;
858
        }
859
860
        public Type TryGetType(Guid typeGuid)
861
        {
862
            if (_dependencyResolver == null)
863
                throw new ArgumentNullException(nameof(_dependencyResolver));
864
865
            return _dependencyResolver.ResolveSpecific(typeGuid, typeof(object), true, _member).Type;
866
        }
867
868
        public TypeInformation GetTypeInformation(Guid typeGuid)
869
        {
870
            if (_dependencyResolver == null)
871
                throw new ArgumentNullException(nameof(_dependencyResolver));
872
873
            return _dependencyResolver.ResolveSpecific(typeGuid, typeof(object), false, _member).TypeInformation;
874
        }
875
876
        public TypeInformation TryGetTypeInformation(Guid typeGuid)
877
        {
878
            if (_dependencyResolver == null)
879
                throw new ArgumentNullException(nameof(_dependencyResolver));
880
881
            return _dependencyResolver.ResolveSpecific(typeGuid, typeof(object), true, _member).TypeInformation;
882
        }
883
884
        private MemberInfo _member;
885
        private DependencyResolver _dependencyResolver;
886
    }
887
888
    class ProfileInformation : IProfileInformation, IInjectionValue
889
    {
890
        public void Prepare(MemberInfo member, DependencyResolver depencencyResolver)
891
        {
892
            if (depencencyResolver == null)
893
                throw new ArgumentNullException(nameof(depencencyResolver));
894
895
            string profileName;
896
            Profile profile;
897
            depencencyResolver.ResolveProfile(member, out profileName, out profile);
898
            ProfileName = profileName;
899
            Profile = profile;
900
        }
901
902
        public string ProfileName { get; private set; }
903
        public Profile Profile { get; private set; }
904
    }
905
906
    class WinFormWrapperProxy : IWinFormWrapperProxy, IInjectionValue
907
    {
908
        public IWinFormWrapper FrameForm { get; private set; }
909
910
        public void Prepare(MemberInfo member, DependencyResolver depencencyResolver)
911
        {
912
            if (depencencyResolver == null)
913
                throw new ArgumentNullException(nameof(depencencyResolver));
914
915
            FrameForm = depencencyResolver.ResolveFrameForm(member);
916
        }
917
    }
918
}