File: cachingcollectioninitializer.cs

package info (click to toggle)
mono-reference-assemblies 3.12.1%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 604,240 kB
  • ctags: 625,505
  • sloc: cs: 3,967,741; xml: 2,793,081; ansic: 418,042; java: 60,435; sh: 14,833; makefile: 11,576; sql: 7,956; perl: 1,467; cpp: 1,446; yacc: 1,203; python: 598; asm: 422; sed: 16; php: 1
file content (75 lines) | stat: -rw-r--r-- 3,490 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.

namespace LazyUnicorns
{
    using System;
    using System.Collections.Concurrent;
    using System.Collections.Generic;
    using System.Data.Entity;
    using System.Data.Entity.Infrastructure;
    using System.Linq;
    using System.Reflection;

    public abstract class CachingCollectionInitializer
    {
        private static readonly ConcurrentDictionary<Type, IList<Tuple<string, Func<DbCollectionEntry, object>>>> _factories
            = new ConcurrentDictionary<Type, IList<Tuple<string, Func<DbCollectionEntry, object>>>>();

        private static readonly MethodInfo _factoryMethodInfo
            = typeof(CachingCollectionInitializer).GetMethod("CreateCollection");

        public virtual Type TryGetElementType(PropertyInfo collectionProperty)
        {
            // We can only replace properties that are declared as ICollection<T> and have a setter.
            var propertyType = collectionProperty.PropertyType;
            if (propertyType.IsGenericType &&
                propertyType.GetGenericTypeDefinition() == typeof(ICollection<>)
                &&
                collectionProperty.GetSetMethod() != null)
            {
                return propertyType.GetGenericArguments().Single();
            }
            return null;
        }

        public virtual void InitializeCollections(DbContext context, object entity)
        {
            var factories = _factories.GetOrAdd(
                entity.GetType(), t =>
                                      {
                                          var list = new List<Tuple<string, Func<DbCollectionEntry, object>>>();

                                          foreach (var property in t.GetProperties())
                                          {
                                              var collectionEntry = context.Entry(entity).Member(property.Name) as DbCollectionEntry;

                                              if (collectionEntry != null)
                                              {
                                                  var elementType = TryGetElementType(property);
                                                  if (elementType != null)
                                                  {
                                                      list.Add(Tuple.Create(property.Name, CreateCollectionFactory(elementType)));
                                                  }
                                              }
                                          }

                                          return list;
                                      });

            foreach (var factory in factories)
            {
                var collectionEntry = context.Entry(entity).Collection(factory.Item1);
                collectionEntry.CurrentValue = factory.Item2(collectionEntry);
            }
        }

        public virtual Func<DbCollectionEntry, object> CreateCollectionFactory(Type elementType)
        {
            return (Func<DbCollectionEntry, object>)Delegate.CreateDelegate(
                typeof(Func<DbCollectionEntry, object>), this,
                _factoryMethodInfo.MakeGenericMethod(elementType));
        }

        public abstract object CreateCollection<TElement>(DbCollectionEntry collectionEntry);
    }
}