Welcome to mirror list, hosted at ThFree Co, Russian Federation.

ObjectItemLoadingSessionData.cs « ObjectLayer « Metadata « Data « System « System.Data.Entity « referencesource « class « mcs - github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: bfb63d99f7ba33295fd781040dee9b5aab6dda1b (plain)
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
//---------------------------------------------------------------------
// <copyright file="ObjectItemLoadingSessionData.cs" company="Microsoft">
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//
// @owner       [....]
// @backupOwner [....]
//---------------------------------------------------------------------
using System.Reflection;
using System.Linq;
using System.Collections.Generic;
using System.Diagnostics;

namespace System.Data.Metadata.Edm
{
    internal sealed class ObjectItemLoadingSessionData
    {
        private Func<Assembly, ObjectItemLoadingSessionData, ObjectItemAssemblyLoader> _loaderFactory;

        // all the types that we encountered while loading - this may contain types from various assemblies
        private readonly Dictionary<string, EdmType> _typesInLoading;
        
        // 

        private bool _conventionBasedRelationshipsAreLoaded = false;

        private LoadMessageLogger _loadMessageLogger;

        // list of errors encountered during loading
        private readonly List<EdmItemError> _errors;

        // keep the list of new assemblies that got loaded in this load assembly call. The reason why we need to keep a seperate
        // list of assemblies is that we keep track of errors, and if there are no errors, only then do we add the list of assemblies
        // to the global cache. Hence global cache is never polluted with invalid assemblies
        private readonly Dictionary<Assembly, MutableAssemblyCacheEntry> _listOfAssembliesLoaded = new Dictionary<Assembly, MutableAssemblyCacheEntry>();

        // List of known assemblies - this list is initially passed by the caller and we keep adding to it, as and when we load
        // an assembly
        private readonly KnownAssembliesSet _knownAssemblies;
        private readonly LockedAssemblyCache _lockedAssemblyCache;
        private readonly HashSet<ObjectItemAssemblyLoader> _loadersThatNeedLevel1PostSessionProcessing;
        private readonly HashSet<ObjectItemAssemblyLoader> _loadersThatNeedLevel2PostSessionProcessing;

        private readonly EdmItemCollection _edmItemCollection;
        private Dictionary<string, KeyValuePair<EdmType, int>> _conventionCSpaceTypeNames;
        private Dictionary<EdmType, EdmType> _cspaceToOspace;
        private object _originalLoaderCookie;
        internal Dictionary<string, EdmType> TypesInLoading { get { return _typesInLoading; } }
        internal Dictionary<Assembly, MutableAssemblyCacheEntry> AssembliesLoaded { get { return _listOfAssembliesLoaded; } }
        internal List<EdmItemError> EdmItemErrors { get { return _errors; } }
        internal KnownAssembliesSet KnownAssemblies { get { return _knownAssemblies; } }
        internal LockedAssemblyCache LockedAssemblyCache { get { return _lockedAssemblyCache; } }
        internal EdmItemCollection EdmItemCollection { get { return _edmItemCollection; } }
        internal Dictionary<EdmType, EdmType> CspaceToOspace { get { return _cspaceToOspace; } }
        internal bool ConventionBasedRelationshipsAreLoaded 
        { 
            get { return _conventionBasedRelationshipsAreLoaded;  }
            set { _conventionBasedRelationshipsAreLoaded = value; }
        }

        internal LoadMessageLogger LoadMessageLogger
        { 
            get 
            { 
                return this._loadMessageLogger; 
            }
        }

        // dictionary of types by name (not including namespace), we also track duplicate names
        // so if one of those types is used we can log an error
        internal Dictionary<string, KeyValuePair<EdmType, int>> ConventionCSpaceTypeNames 
        { 
            get 
            {
                if (_edmItemCollection != null && _conventionCSpaceTypeNames == null)
                {
                    _conventionCSpaceTypeNames = new Dictionary<string, KeyValuePair<EdmType, int>>();

                    // create the map and cache it
                    foreach (var edmType in _edmItemCollection.GetItems<EdmType>())
                    {
                        if ((edmType is StructuralType && edmType.BuiltInTypeKind != BuiltInTypeKind.AssociationType) || Helper.IsEnumType(edmType))
                        {

                            KeyValuePair<EdmType, int> pair;
                            if (_conventionCSpaceTypeNames.TryGetValue(edmType.Name, out pair))
                            {
                                _conventionCSpaceTypeNames[edmType.Name] = new KeyValuePair<EdmType, int>(pair.Key, pair.Value + 1);
                            }
                            else
                            {
                                pair = new KeyValuePair<EdmType, int>(edmType, 1);
                                _conventionCSpaceTypeNames.Add(edmType.Name, pair);
                            }
                        }
                    }
                }
                return _conventionCSpaceTypeNames;
            } 
        }

        internal Func<Assembly, ObjectItemLoadingSessionData, ObjectItemAssemblyLoader> ObjectItemAssemblyLoaderFactory
        {
            get { return _loaderFactory; }
            set
            {
                if (_loaderFactory != value)
                {
                    Debug.Assert(_loaderFactory == null || _typesInLoading.Count == 0, "Only reset the factory after types have not been loaded or load from the cache");
                    _loaderFactory = value;
                }
            }
        }

        internal object LoaderCookie
        {
            get
            {
                // be sure we get the same factory/cookie as we had before... if we had one
                if (_originalLoaderCookie != null)
                {
                    Debug.Assert(_loaderFactory == null ||
                                 (object)_loaderFactory == _originalLoaderCookie, "The loader factory should determine the next loader, so we should always have the same loader factory");
                    return _originalLoaderCookie;
                }

                return _loaderFactory;
            }
        }
        internal ObjectItemLoadingSessionData(KnownAssembliesSet knownAssemblies, LockedAssemblyCache lockedAssemblyCache, EdmItemCollection edmItemCollection, Action<String> logLoadMessage, object loaderCookie)
        {
            Debug.Assert(loaderCookie == null || loaderCookie is Func<Assembly, ObjectItemLoadingSessionData, ObjectItemAssemblyLoader>, "This is a bad loader cookie");
            
            _typesInLoading = new Dictionary<string, EdmType>(StringComparer.Ordinal);
            _errors = new List<EdmItemError>();
            _knownAssemblies = knownAssemblies;
            _lockedAssemblyCache = lockedAssemblyCache;
            _loadersThatNeedLevel1PostSessionProcessing = new HashSet<ObjectItemAssemblyLoader>();
            _loadersThatNeedLevel2PostSessionProcessing = new HashSet<ObjectItemAssemblyLoader>();
            _edmItemCollection = edmItemCollection;
            _loadMessageLogger = new LoadMessageLogger(logLoadMessage);
            _cspaceToOspace = new Dictionary<EdmType, EdmType>();
            _loaderFactory = (Func<Assembly, ObjectItemLoadingSessionData, ObjectItemAssemblyLoader>)loaderCookie;
            _originalLoaderCookie = loaderCookie;
            if (_loaderFactory == ObjectItemConventionAssemblyLoader.Create && _edmItemCollection != null)
            {
                foreach (KnownAssemblyEntry entry in _knownAssemblies.GetEntries(_loaderFactory, edmItemCollection))
                {
                    foreach (EdmType type in entry.CacheEntry.TypesInAssembly.OfType<EdmType>())
                    {
                        if (Helper.IsEntityType(type))
                        {
                            ClrEntityType entityType = (ClrEntityType)type;
                            _cspaceToOspace.Add(_edmItemCollection.GetItem<StructuralType>(entityType.CSpaceTypeName), entityType);
                        }
                        else if (Helper.IsComplexType(type))
                        {
                            ClrComplexType complexType = (ClrComplexType)type;
                            _cspaceToOspace.Add(_edmItemCollection.GetItem<StructuralType>(complexType.CSpaceTypeName), complexType);
                        }
                        else if(Helper.IsEnumType(type))
                        {
                            ClrEnumType enumType = (ClrEnumType)type;
                            _cspaceToOspace.Add(_edmItemCollection.GetItem<EnumType>(enumType.CSpaceTypeName), enumType);
                        }
                        else
                        {
                            Debug.Assert(Helper.IsAssociationType(type));
                            _cspaceToOspace.Add(_edmItemCollection.GetItem<StructuralType>(type.FullName), type);
                        }
                    }
                }
            }

        }

        internal void RegisterForLevel1PostSessionProcessing(ObjectItemAssemblyLoader loader)
        {
            _loadersThatNeedLevel1PostSessionProcessing.Add(loader);
        }

        internal void RegisterForLevel2PostSessionProcessing(ObjectItemAssemblyLoader loader)
        {
            _loadersThatNeedLevel2PostSessionProcessing.Add(loader);
        }
        
        internal void CompleteSession()
        {
            foreach (ObjectItemAssemblyLoader loader in _loadersThatNeedLevel1PostSessionProcessing)
            {
                loader.OnLevel1SessionProcessing();
            }

            foreach (ObjectItemAssemblyLoader loader in _loadersThatNeedLevel2PostSessionProcessing)
            {
                loader.OnLevel2SessionProcessing();
            }
        }
    }
}