You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@ -0,0 +1,164 @@
|
||||
//---------------------------------------------------------------------
|
||||
// <copyright file="AssemblyCache.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//
|
||||
// @owner [....]
|
||||
// @backupOwner [....]
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common.Utils;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
|
||||
namespace System.Data.Metadata.Edm
|
||||
{
|
||||
internal static class AssemblyCache
|
||||
{
|
||||
// Global Assembly Cache
|
||||
private readonly static Dictionary<Assembly, ImmutableAssemblyCacheEntry> s_globalAssemblyCache = new Dictionary<Assembly, ImmutableAssemblyCacheEntry>();
|
||||
private static object _assemblyCacheLock = new object();
|
||||
|
||||
//List of assemblies having view gen attribute. We cache these things if we discover
|
||||
//these assemblies while looking for O-space metadata.
|
||||
private static IList<Assembly> s_viewGenAssemblies = new ThreadSafeList<Assembly>();
|
||||
|
||||
internal static LockedAssemblyCache AquireLockedAssemblyCache()
|
||||
{
|
||||
return new LockedAssemblyCache(_assemblyCacheLock, s_globalAssemblyCache);
|
||||
}
|
||||
|
||||
internal static void LoadAssembly(Assembly assembly, bool loadReferencedAssemblies,
|
||||
KnownAssembliesSet knownAssemblies, out Dictionary<string, EdmType> typesInLoading, out List<EdmItemError> errors)
|
||||
{
|
||||
object loaderCookie = null;
|
||||
LoadAssembly(assembly, loadReferencedAssemblies, knownAssemblies, null, null, ref loaderCookie, out typesInLoading, out errors);
|
||||
}
|
||||
|
||||
internal static void LoadAssembly(Assembly assembly, bool loadReferencedAssemblies,
|
||||
KnownAssembliesSet knownAssemblies, EdmItemCollection edmItemCollection, Action<String> logLoadMessage, ref object loaderCookie, out Dictionary<string, EdmType> typesInLoading, out List<EdmItemError> errors)
|
||||
{
|
||||
Debug.Assert(loaderCookie == null || loaderCookie is Func<Assembly, ObjectItemLoadingSessionData, ObjectItemAssemblyLoader>, "This is a bad loader cookie");
|
||||
typesInLoading = null;
|
||||
errors = null;
|
||||
|
||||
using (LockedAssemblyCache lockedAssemblyCache = AssemblyCache.AquireLockedAssemblyCache())
|
||||
{
|
||||
ObjectItemLoadingSessionData loadingData = new ObjectItemLoadingSessionData(knownAssemblies, lockedAssemblyCache, edmItemCollection, logLoadMessage, loaderCookie);
|
||||
|
||||
LoadAssembly(assembly, loadReferencedAssemblies, loadingData);
|
||||
loaderCookie = loadingData.LoaderCookie;
|
||||
// resolve references to top level types (base types, navigation properties returns and associations, and complex type properties)
|
||||
loadingData.CompleteSession();
|
||||
|
||||
if (loadingData.EdmItemErrors.Count == 0)
|
||||
{
|
||||
// do the validation for the all the new types
|
||||
// Now, perform validation on all the new types
|
||||
EdmValidator validator = new EdmValidator();
|
||||
validator.SkipReadOnlyItems = true;
|
||||
validator.Validate(loadingData.TypesInLoading.Values, loadingData.EdmItemErrors);
|
||||
// Update the global cache if there are no errors
|
||||
if (loadingData.EdmItemErrors.Count == 0)
|
||||
{
|
||||
if (ObjectItemAssemblyLoader.IsAttributeLoader(loadingData.ObjectItemAssemblyLoaderFactory))
|
||||
{
|
||||
// we only cache items from the attribute loader globally, the
|
||||
// items loaded by convention will change depending on the cspace
|
||||
// provided. cspace will have a cache of it's own for assemblies
|
||||
UpdateCache(lockedAssemblyCache, loadingData.AssembliesLoaded);
|
||||
}
|
||||
else if (loadingData.EdmItemCollection != null &&
|
||||
ObjectItemAssemblyLoader.IsConventionLoader(loadingData.ObjectItemAssemblyLoaderFactory))
|
||||
{
|
||||
UpdateCache(loadingData.EdmItemCollection, loadingData.AssembliesLoaded);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (loadingData.TypesInLoading.Count > 0)
|
||||
{
|
||||
foreach (EdmType edmType in loadingData.TypesInLoading.Values)
|
||||
{
|
||||
edmType.SetReadOnly();
|
||||
}
|
||||
}
|
||||
|
||||
// Update the out parameters once you are done with loading
|
||||
typesInLoading = loadingData.TypesInLoading;
|
||||
errors = loadingData.EdmItemErrors;
|
||||
}
|
||||
}
|
||||
|
||||
private static void LoadAssembly(Assembly assembly, bool loadReferencedAssemblies, ObjectItemLoadingSessionData loadingData)
|
||||
{
|
||||
// Check if the assembly is already loaded
|
||||
KnownAssemblyEntry entry;
|
||||
bool shouldLoadReferences = false;
|
||||
if (loadingData.KnownAssemblies.TryGetKnownAssembly(assembly, loadingData.ObjectItemAssemblyLoaderFactory, loadingData.EdmItemCollection, out entry))
|
||||
{
|
||||
shouldLoadReferences = !entry.ReferencedAssembliesAreLoaded && loadReferencedAssemblies;
|
||||
}
|
||||
else
|
||||
{
|
||||
ObjectItemAssemblyLoader loader = ObjectItemAssemblyLoader.CreateLoader(assembly, loadingData);
|
||||
loader.Load();
|
||||
shouldLoadReferences = loadReferencedAssemblies;
|
||||
}
|
||||
|
||||
if (shouldLoadReferences)
|
||||
{
|
||||
if (entry == null && loadingData.KnownAssemblies.TryGetKnownAssembly(assembly, loadingData.ObjectItemAssemblyLoaderFactory, loadingData.EdmItemCollection, out entry) ||
|
||||
entry != null)
|
||||
{
|
||||
entry.ReferencedAssembliesAreLoaded = true;
|
||||
}
|
||||
Debug.Assert(entry != null, "we should always have an entry, why don't we?");
|
||||
|
||||
// We will traverse through all the statically linked assemblies and their dependencies.
|
||||
// Only assemblies with the EdmSchemaAttribute will be loaded and rest will be ignored
|
||||
|
||||
// Even if the schema attribute is missing, we should still check all the dependent assemblies
|
||||
// any of the dependent assemblies can have the schema attribute
|
||||
|
||||
// After the given assembly has been loaded, check on the flag in _knownAssemblies to see if it has already
|
||||
// been recursively loaded. The flag can be true if it was already loaded before this function was called
|
||||
foreach (Assembly referencedAssembly in MetadataAssemblyHelper.GetNonSystemReferencedAssemblies(assembly))
|
||||
{
|
||||
// filter out "known" assemblies to prevent unnecessary loading
|
||||
// recursive call
|
||||
LoadAssembly(referencedAssembly, loadReferencedAssemblies, loadingData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void UpdateCache(EdmItemCollection edmItemCollection, Dictionary<Assembly, MutableAssemblyCacheEntry> assemblies)
|
||||
{
|
||||
foreach (var entry in assemblies)
|
||||
{
|
||||
edmItemCollection.ConventionalOcCache.AddAssemblyToOcCacheFromAssemblyCache(
|
||||
entry.Key, new ImmutableAssemblyCacheEntry(entry.Value));
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateCache(LockedAssemblyCache lockedAssemblyCache, Dictionary<Assembly, MutableAssemblyCacheEntry> assemblies)
|
||||
{
|
||||
|
||||
foreach (KeyValuePair<Assembly, MutableAssemblyCacheEntry> entry in assemblies)
|
||||
{
|
||||
// Add all the assemblies from the loading context to the global cache
|
||||
lockedAssemblyCache.Add(entry.Key, new ImmutableAssemblyCacheEntry(entry.Value));
|
||||
}
|
||||
}
|
||||
|
||||
internal static IList<Assembly> ViewGenerationAssemblies
|
||||
{
|
||||
get
|
||||
{
|
||||
return s_viewGenAssemblies;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
//---------------------------------------------------------------------
|
||||
// <copyright file="AssemblyCacheEntry.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//
|
||||
// @owner [....]
|
||||
// @backupOwner [....]
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace System.Data.Metadata.Edm
|
||||
{
|
||||
internal abstract class AssemblyCacheEntry
|
||||
{
|
||||
internal abstract IList<EdmType> TypesInAssembly { get; }
|
||||
internal abstract IList<Assembly> ClosureAssemblies { get; }
|
||||
|
||||
internal bool TryGetEdmType(string typeName, out EdmType edmType)
|
||||
{
|
||||
edmType = null;
|
||||
foreach (EdmType loadedEdmType in this.TypesInAssembly)
|
||||
{
|
||||
if (loadedEdmType.Identity == typeName)
|
||||
{
|
||||
edmType = loadedEdmType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (edmType != null);
|
||||
}
|
||||
|
||||
internal bool ContainsType(string typeName)
|
||||
{
|
||||
EdmType edmType = null;
|
||||
return TryGetEdmType(typeName, out edmType);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
//---------------------------------------------------------------------
|
||||
// <copyright file="ImmutableAssemblyCacheEntry.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//
|
||||
// @owner [....]
|
||||
// @backupOwner [....]
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace System.Data.Metadata.Edm
|
||||
{
|
||||
internal partial class ImmutableAssemblyCacheEntry : AssemblyCacheEntry
|
||||
{
|
||||
// types in "this" assembly
|
||||
private readonly System.Collections.ObjectModel.ReadOnlyCollection<EdmType> _typesInAssembly;
|
||||
// other assemblies referenced by types we care about in "this" assembly
|
||||
private readonly System.Collections.ObjectModel.ReadOnlyCollection<Assembly> _closureAssemblies;
|
||||
internal ImmutableAssemblyCacheEntry(MutableAssemblyCacheEntry mutableEntry)
|
||||
{
|
||||
_typesInAssembly = new List<EdmType>(mutableEntry.TypesInAssembly).AsReadOnly();
|
||||
_closureAssemblies = new List<Assembly>(mutableEntry.ClosureAssemblies).AsReadOnly();
|
||||
}
|
||||
|
||||
internal override IList<EdmType> TypesInAssembly
|
||||
{
|
||||
get { return _typesInAssembly; }
|
||||
}
|
||||
|
||||
internal override IList<Assembly> ClosureAssemblies
|
||||
{
|
||||
get { return _closureAssemblies; }
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
//---------------------------------------------------------------------
|
||||
// <copyright file="KnownAssembliesSet.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//
|
||||
// @owner [....]
|
||||
// @backupOwner [....]
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace System.Data.Metadata.Edm
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is responsible for keeping track of which assemblies we have already
|
||||
/// considered so we don't reconsider them again.
|
||||
///
|
||||
/// The current rules for an assembly to be "seen" is
|
||||
/// 1. It is already in our dictionary
|
||||
/// AND
|
||||
/// 1. We are in attribute loading mode
|
||||
/// OR
|
||||
/// 2. We have seen it already with a non null EdmItemCollection
|
||||
/// OR
|
||||
/// 3. We are seeing it with a null EdmItemCollection this time
|
||||
/// </summary>
|
||||
internal class KnownAssembliesSet
|
||||
{
|
||||
private Dictionary<Assembly, KnownAssemblyEntry> _assemblies;
|
||||
internal KnownAssembliesSet()
|
||||
{
|
||||
_assemblies = new Dictionary<Assembly, KnownAssemblyEntry>();
|
||||
}
|
||||
|
||||
internal KnownAssembliesSet(KnownAssembliesSet set)
|
||||
{
|
||||
_assemblies = new Dictionary<Assembly, KnownAssemblyEntry>(set._assemblies);
|
||||
}
|
||||
|
||||
internal bool TryGetKnownAssembly(Assembly assembly, object loaderCookie, EdmItemCollection itemCollection, out KnownAssemblyEntry entry)
|
||||
{
|
||||
if (!_assemblies.TryGetValue(assembly, out entry))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!entry.HaveSeenInCompatibleContext(loaderCookie, itemCollection))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal IEnumerable<Assembly> Assemblies
|
||||
{
|
||||
get { return _assemblies.Keys; }
|
||||
}
|
||||
|
||||
public IEnumerable<KnownAssemblyEntry> GetEntries(object loaderCookie, EdmItemCollection itemCollection)
|
||||
{
|
||||
return _assemblies.Values.Where(e => e.HaveSeenInCompatibleContext(loaderCookie, itemCollection));
|
||||
}
|
||||
|
||||
internal bool Contains(Assembly assembly, object loaderCookie, EdmItemCollection itemCollection)
|
||||
{
|
||||
KnownAssemblyEntry entry;
|
||||
return TryGetKnownAssembly(assembly, loaderCookie, itemCollection, out entry);
|
||||
}
|
||||
|
||||
internal void Add(Assembly assembly, KnownAssemblyEntry knownAssemblyEntry)
|
||||
{
|
||||
KnownAssemblyEntry current;
|
||||
if (_assemblies.TryGetValue(assembly, out current))
|
||||
{
|
||||
Debug.Assert(current.SeenWithEdmItemCollection != knownAssemblyEntry.SeenWithEdmItemCollection &&
|
||||
knownAssemblyEntry.SeenWithEdmItemCollection, "should only be updating if we haven't seen it with an edmItemCollection yet.");
|
||||
_assemblies[assembly] = knownAssemblyEntry;
|
||||
}
|
||||
else
|
||||
{
|
||||
_assemblies.Add(assembly, knownAssemblyEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
//---------------------------------------------------------------------
|
||||
// <copyright file="KnownAssemblyEntry.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//
|
||||
// @owner [....]
|
||||
// @backupOwner [....]
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace System.Data.Metadata.Edm
|
||||
{
|
||||
internal sealed class KnownAssemblyEntry
|
||||
{
|
||||
private readonly AssemblyCacheEntry _cacheEntry;
|
||||
private bool _referencedAssembliesAreLoaded;
|
||||
private bool _seenWithEdmItemCollection;
|
||||
|
||||
internal KnownAssemblyEntry(AssemblyCacheEntry cacheEntry, bool seenWithEdmItemCollection)
|
||||
{
|
||||
Debug.Assert(cacheEntry != null, "Found a null cacheEntry");
|
||||
_cacheEntry = cacheEntry;
|
||||
_referencedAssembliesAreLoaded = false;
|
||||
_seenWithEdmItemCollection = seenWithEdmItemCollection;
|
||||
}
|
||||
|
||||
internal AssemblyCacheEntry CacheEntry
|
||||
{
|
||||
get { return _cacheEntry; }
|
||||
}
|
||||
|
||||
public bool ReferencedAssembliesAreLoaded
|
||||
{
|
||||
get { return _referencedAssembliesAreLoaded; }
|
||||
set { _referencedAssembliesAreLoaded = value; }
|
||||
}
|
||||
|
||||
public bool SeenWithEdmItemCollection
|
||||
{
|
||||
get { return _seenWithEdmItemCollection; }
|
||||
set { _seenWithEdmItemCollection = value; }
|
||||
}
|
||||
|
||||
public bool HaveSeenInCompatibleContext(object loaderCookie, EdmItemCollection itemCollection)
|
||||
{
|
||||
// a new "context" is only when we have not seen this assembly with an itemCollection that is non-null
|
||||
// and we now have a non-null itemCollection, and we are not already in AttributeLoader mode.
|
||||
return SeenWithEdmItemCollection ||
|
||||
itemCollection == null ||
|
||||
ObjectItemAssemblyLoader.IsAttributeLoader(loaderCookie);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
//---------------------------------------------------------------------
|
||||
// <copyright file="ObjectItemLoadingSessionData.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//
|
||||
// @owner [....]
|
||||
// @backupOwner [....]
|
||||
//---------------------------------------------------------------------
|
||||
namespace System.Data.Metadata.Edm
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Entity;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
internal class LoadMessageLogger
|
||||
{
|
||||
private Action<String> _logLoadMessage;
|
||||
private Dictionary<EdmType, StringBuilder> _messages = new Dictionary<EdmType, StringBuilder>();
|
||||
|
||||
internal LoadMessageLogger(Action<String> logLoadMessage)
|
||||
{
|
||||
this._logLoadMessage = logLoadMessage;
|
||||
}
|
||||
|
||||
internal void LogLoadMessage(string message, EdmType relatedType)
|
||||
{
|
||||
if (_logLoadMessage != null)
|
||||
{
|
||||
_logLoadMessage(message);
|
||||
}
|
||||
|
||||
LogMessagesWithTypeInfo(message, relatedType);
|
||||
}
|
||||
|
||||
internal string CreateErrorMessageWithTypeSpecificLoadLogs(string errorMessage, EdmType relatedType)
|
||||
{
|
||||
return new StringBuilder(errorMessage)
|
||||
.AppendLine(this.GetTypeRelatedLogMessage(relatedType)).ToString();
|
||||
}
|
||||
|
||||
private string GetTypeRelatedLogMessage(EdmType relatedType)
|
||||
{
|
||||
Debug.Assert(relatedType != null, "have to pass in a type to get the message");
|
||||
|
||||
if (this._messages.ContainsKey(relatedType))
|
||||
{
|
||||
return new StringBuilder()
|
||||
.AppendLine()
|
||||
.AppendLine(Strings.ExtraInfo)
|
||||
.AppendLine(this._messages[relatedType].ToString()).ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
private void LogMessagesWithTypeInfo(string message, EdmType relatedType)
|
||||
{
|
||||
Debug.Assert(relatedType != null, "have to have a type with this message");
|
||||
|
||||
if (this._messages.ContainsKey(relatedType))
|
||||
{
|
||||
// if this type already contains loading message, append the new message to the end
|
||||
this._messages[relatedType].AppendLine(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
this._messages.Add(relatedType, new StringBuilder(message));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
//---------------------------------------------------------------------
|
||||
// <copyright file="LockedAssemblyCache.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//
|
||||
// @owner [....]
|
||||
// @backupOwner [....]
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
|
||||
namespace System.Data.Metadata.Edm
|
||||
{
|
||||
internal class LockedAssemblyCache : IDisposable
|
||||
{
|
||||
private object _lockObject;
|
||||
private Dictionary<Assembly, ImmutableAssemblyCacheEntry> _globalAssemblyCache;
|
||||
internal LockedAssemblyCache(object lockObject, Dictionary<Assembly, ImmutableAssemblyCacheEntry> globalAssemblyCache)
|
||||
{
|
||||
_lockObject = lockObject;
|
||||
_globalAssemblyCache = globalAssemblyCache;
|
||||
#pragma warning disable 0618
|
||||
//@
|
||||
Monitor.Enter(_lockObject);
|
||||
#pragma warning restore 0618
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// Technically, calling GC.SuppressFinalize is not required because the class does not
|
||||
// have a finalizer, but it does no harm, protects against the case where a finalizer is added
|
||||
// in the future, and prevents an FxCop warning.
|
||||
GC.SuppressFinalize(this);
|
||||
Monitor.Exit(_lockObject);
|
||||
_lockObject = null;
|
||||
_globalAssemblyCache = null;
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
private void AssertLockedByThisThread()
|
||||
{
|
||||
bool entered = false;
|
||||
Monitor.TryEnter(_lockObject, ref entered);
|
||||
if (entered)
|
||||
{
|
||||
Monitor.Exit(_lockObject);
|
||||
}
|
||||
|
||||
Debug.Assert(entered, "The cache is being accessed by a thread that isn't holding the lock");
|
||||
}
|
||||
|
||||
internal bool TryGetValue(Assembly assembly, out ImmutableAssemblyCacheEntry cacheEntry)
|
||||
{
|
||||
AssertLockedByThisThread();
|
||||
return _globalAssemblyCache.TryGetValue(assembly, out cacheEntry);
|
||||
}
|
||||
|
||||
internal void Add(Assembly assembly, ImmutableAssemblyCacheEntry assemblyCacheEntry)
|
||||
{
|
||||
AssertLockedByThisThread();
|
||||
_globalAssemblyCache.Add(assembly, assemblyCacheEntry);
|
||||
}
|
||||
|
||||
internal void Clear()
|
||||
{
|
||||
AssertLockedByThisThread();
|
||||
_globalAssemblyCache.Clear();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
//---------------------------------------------------------------------
|
||||
// <copyright file="MetadataAssemblyHelper.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//
|
||||
// @owner [....]
|
||||
// @backupOwner [....]
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
using System.Reflection;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Data.Common.Utils;
|
||||
|
||||
namespace System.Data.Metadata.Edm
|
||||
{
|
||||
internal static class MetadataAssemblyHelper
|
||||
{
|
||||
static byte [] EcmaPublicKeyToken = System.Data.EntityModel.SchemaObjectModel.ScalarType.ConvertToByteArray(AssemblyRef.EcmaPublicKey);
|
||||
static byte [] MsPublicKeyToken = System.Data.EntityModel.SchemaObjectModel.ScalarType.ConvertToByteArray(AssemblyRef.MicrosoftPublicKey);
|
||||
private static Memoizer<Assembly, bool> _filterAssemblyCacheByAssembly = new Memoizer<Assembly, bool>(MetadataAssemblyHelper.ComputeShouldFilterAssembly, EqualityComparer<Assembly>.Default);
|
||||
|
||||
internal static Assembly SafeLoadReferencedAssembly(AssemblyName assemblyName)
|
||||
{
|
||||
Assembly assembly = null;
|
||||
|
||||
try
|
||||
{
|
||||
assembly = Assembly.Load(assemblyName);
|
||||
}
|
||||
catch (System.IO.FileNotFoundException)
|
||||
{
|
||||
// See 552932: ObjectItemCollection: fails on referenced assemblies that are not available
|
||||
}
|
||||
|
||||
return assembly;
|
||||
}
|
||||
|
||||
private static bool ComputeShouldFilterAssembly(Assembly assembly)
|
||||
{
|
||||
AssemblyName assemblyName = new AssemblyName(assembly.FullName);
|
||||
return ShouldFilterAssembly(assemblyName);
|
||||
}
|
||||
|
||||
internal static bool ShouldFilterAssembly(Assembly assembly)
|
||||
{
|
||||
return _filterAssemblyCacheByAssembly.Evaluate(assembly);
|
||||
}
|
||||
|
||||
/// <summary>Is the assembly and its referened assemblies not expected to have any metadata</summary>
|
||||
private static bool ShouldFilterAssembly(AssemblyName assemblyName)
|
||||
{
|
||||
return (ArePublicKeyTokensEqual(assemblyName.GetPublicKeyToken(), EcmaPublicKeyToken) ||
|
||||
ArePublicKeyTokensEqual(assemblyName.GetPublicKeyToken(), MsPublicKeyToken));
|
||||
}
|
||||
|
||||
private static bool ArePublicKeyTokensEqual(byte [] left, byte [] right)
|
||||
{
|
||||
// some assemblies don't have public keys
|
||||
if (left.Length != right.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < left.Length; i++)
|
||||
{
|
||||
if (left[i] != right[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
internal static IEnumerable<Assembly> GetNonSystemReferencedAssemblies(Assembly assembly)
|
||||
{
|
||||
foreach (AssemblyName name in assembly.GetReferencedAssemblies())
|
||||
{
|
||||
if (!ShouldFilterAssembly(name))
|
||||
{
|
||||
Assembly referenceAssembly = SafeLoadReferencedAssembly(name);
|
||||
if(referenceAssembly != null )
|
||||
{
|
||||
yield return referenceAssembly;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
//---------------------------------------------------------------------
|
||||
// <copyright file="MutableAssemblyCacheEntry.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//
|
||||
// @owner [....]
|
||||
// @backupOwner [....]
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace System.Data.Metadata.Edm
|
||||
{
|
||||
internal partial class MutableAssemblyCacheEntry : AssemblyCacheEntry
|
||||
{
|
||||
// types in "this" assembly
|
||||
private readonly List<EdmType> _typesInAssembly = new List<EdmType>();
|
||||
// other assemblies referenced by types we care about in "this" assembly
|
||||
private readonly List<Assembly> _closureAssemblies = new List<Assembly>();
|
||||
|
||||
internal override IList<EdmType> TypesInAssembly
|
||||
{
|
||||
get { return _typesInAssembly; }
|
||||
}
|
||||
|
||||
internal override IList<Assembly> ClosureAssemblies
|
||||
{
|
||||
get { return _closureAssemblies; }
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,168 @@
|
||||
//---------------------------------------------------------------------
|
||||
// <copyright file="ObjectItemAssemblyLoader.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//
|
||||
// @owner [....]
|
||||
// @backupOwner [....]
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
namespace System.Data.Metadata.Edm
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Entity;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
|
||||
internal abstract class ObjectItemAssemblyLoader
|
||||
{
|
||||
protected const BindingFlags PropertyReflectionBindingFlags = BindingFlags.DeclaredOnly |
|
||||
BindingFlags.Instance |
|
||||
BindingFlags.Public |
|
||||
BindingFlags.NonPublic;
|
||||
|
||||
private readonly ObjectItemLoadingSessionData _sessionData;
|
||||
private Assembly _assembly;
|
||||
private AssemblyCacheEntry _cacheEntry;
|
||||
|
||||
protected ObjectItemAssemblyLoader(Assembly assembly, AssemblyCacheEntry cacheEntry, ObjectItemLoadingSessionData sessionData)
|
||||
{
|
||||
_assembly = assembly;
|
||||
_cacheEntry = cacheEntry;
|
||||
_sessionData = sessionData;
|
||||
}
|
||||
|
||||
internal virtual void Load()
|
||||
{
|
||||
AddToAssembliesLoaded();
|
||||
|
||||
LoadTypesFromAssembly();
|
||||
|
||||
AddToKnownAssemblies();
|
||||
|
||||
LoadClosureAssemblies();
|
||||
}
|
||||
|
||||
protected abstract void AddToAssembliesLoaded();
|
||||
protected abstract void LoadTypesFromAssembly();
|
||||
protected virtual void LoadClosureAssemblies()
|
||||
{
|
||||
LoadAssemblies(CacheEntry.ClosureAssemblies, SessionData);
|
||||
}
|
||||
|
||||
internal virtual void OnLevel1SessionProcessing() { }
|
||||
internal virtual void OnLevel2SessionProcessing() { }
|
||||
|
||||
internal static ObjectItemAssemblyLoader CreateLoader(Assembly assembly, ObjectItemLoadingSessionData sessionData)
|
||||
{
|
||||
ImmutableAssemblyCacheEntry cacheEntry;
|
||||
|
||||
// KnownAssembly -> NoOp
|
||||
// Inside the LockedAssemblyCache means it is an attribute based assembly -> Cachedassembly
|
||||
// Inside the OcCache on EdmItemCollection -> cachedassembly
|
||||
// If none of above, setup the LoaderFactory based on the current assembly and EdmItemCollection
|
||||
if (sessionData.KnownAssemblies.Contains(assembly, sessionData.ObjectItemAssemblyLoaderFactory, sessionData.EdmItemCollection))
|
||||
{
|
||||
return new ObjectItemNoOpAssemblyLoader(assembly, sessionData);
|
||||
}
|
||||
else if (sessionData.LockedAssemblyCache.TryGetValue(assembly, out cacheEntry))
|
||||
{
|
||||
if (sessionData.ObjectItemAssemblyLoaderFactory == null)
|
||||
{
|
||||
if (cacheEntry.TypesInAssembly.Count != 0)
|
||||
{
|
||||
// we are loading based on attributes now
|
||||
sessionData.ObjectItemAssemblyLoaderFactory = ObjectItemAttributeAssemblyLoader.Create;
|
||||
}
|
||||
// if types in assembly are 0, don't commit to any loader yet
|
||||
}
|
||||
else if (sessionData.ObjectItemAssemblyLoaderFactory != ObjectItemAttributeAssemblyLoader.Create)
|
||||
{
|
||||
// we were loading in convention mode, and ran into an assembly that can't be loaded by convention
|
||||
// we know this because all cached assemblies are attribute based at the moment.
|
||||
sessionData.EdmItemErrors.Add(new EdmItemError(Strings.Validator_OSpace_Convention_AttributeAssemblyReferenced(assembly.FullName), null));
|
||||
}
|
||||
return new ObjectItemCachedAssemblyLoader(assembly, cacheEntry, sessionData);
|
||||
}
|
||||
else if (sessionData.EdmItemCollection != null &&
|
||||
sessionData.EdmItemCollection.ConventionalOcCache.TryGetConventionalOcCacheFromAssemblyCache(
|
||||
assembly, out cacheEntry))
|
||||
{
|
||||
sessionData.ObjectItemAssemblyLoaderFactory = ObjectItemConventionAssemblyLoader.Create;
|
||||
return new ObjectItemCachedAssemblyLoader(assembly, cacheEntry, sessionData);
|
||||
}
|
||||
else if (sessionData.ObjectItemAssemblyLoaderFactory == null)
|
||||
{
|
||||
if (ObjectItemAttributeAssemblyLoader.IsSchemaAttributePresent(assembly))
|
||||
{
|
||||
sessionData.ObjectItemAssemblyLoaderFactory = ObjectItemAttributeAssemblyLoader.Create;
|
||||
}
|
||||
else if (ObjectItemConventionAssemblyLoader.SessionContainsConventionParameters(sessionData))
|
||||
{
|
||||
sessionData.ObjectItemAssemblyLoaderFactory = ObjectItemConventionAssemblyLoader.Create;
|
||||
}
|
||||
}
|
||||
|
||||
if (sessionData.ObjectItemAssemblyLoaderFactory != null)
|
||||
{
|
||||
return sessionData.ObjectItemAssemblyLoaderFactory(assembly, sessionData);
|
||||
}
|
||||
|
||||
return new ObjectItemNoOpAssemblyLoader(assembly, sessionData);
|
||||
|
||||
}
|
||||
|
||||
internal static bool IsAttributeLoader(object loaderCookie)
|
||||
{
|
||||
Debug.Assert(loaderCookie == null || loaderCookie is Func<Assembly, ObjectItemLoadingSessionData, ObjectItemAssemblyLoader>, "Non loader cookie passed in");
|
||||
return IsAttributeLoader(loaderCookie as Func<Assembly, ObjectItemLoadingSessionData, ObjectItemAssemblyLoader>);
|
||||
}
|
||||
|
||||
internal static bool IsAttributeLoader(Func<Assembly, ObjectItemLoadingSessionData, ObjectItemAssemblyLoader> loaderFactory)
|
||||
{
|
||||
if (loaderFactory == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return loaderFactory == ObjectItemAttributeAssemblyLoader.Create;
|
||||
}
|
||||
|
||||
internal static bool IsConventionLoader(Func<Assembly, ObjectItemLoadingSessionData, ObjectItemAssemblyLoader> loaderFactory)
|
||||
{
|
||||
if (loaderFactory == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return loaderFactory == ObjectItemConventionAssemblyLoader.Create;
|
||||
}
|
||||
|
||||
protected virtual void AddToKnownAssemblies()
|
||||
{
|
||||
Debug.Assert(!_sessionData.KnownAssemblies.Contains(_assembly, SessionData.ObjectItemAssemblyLoaderFactory, _sessionData.EdmItemCollection), "This assembly must not be present in the list of known assemblies");
|
||||
_sessionData.KnownAssemblies.Add(_assembly, new KnownAssemblyEntry(CacheEntry, SessionData.EdmItemCollection != null));
|
||||
}
|
||||
|
||||
protected static void LoadAssemblies(IEnumerable<Assembly> assemblies, ObjectItemLoadingSessionData sessionData)
|
||||
{
|
||||
foreach (Assembly assembly in assemblies)
|
||||
{
|
||||
ObjectItemAssemblyLoader loader = ObjectItemAssemblyLoader.CreateLoader(assembly, sessionData);
|
||||
loader.Load();
|
||||
}
|
||||
}
|
||||
|
||||
protected bool TryGetPrimitiveType(Type type, out PrimitiveType primitiveType)
|
||||
{
|
||||
return ClrProviderManifest.Instance.TryGetPrimitiveType(Nullable.GetUnderlyingType(type) ?? type, out primitiveType);
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected ObjectItemLoadingSessionData SessionData { get { return _sessionData; } }
|
||||
protected Assembly SourceAssembly { get { return _assembly; } }
|
||||
protected AssemblyCacheEntry CacheEntry { get { return _cacheEntry; } }
|
||||
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,43 @@
|
||||
//---------------------------------------------------------------------
|
||||
// <copyright file="ObjectItemCachedAssemblyLoader.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//
|
||||
// @owner [....]
|
||||
// @backupOwner [....]
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
namespace System.Data.Metadata.Edm
|
||||
{
|
||||
using System.Reflection;
|
||||
|
||||
internal sealed class ObjectItemCachedAssemblyLoader : ObjectItemAssemblyLoader
|
||||
{
|
||||
private new ImmutableAssemblyCacheEntry CacheEntry { get { return (ImmutableAssemblyCacheEntry)base.CacheEntry; } }
|
||||
|
||||
internal ObjectItemCachedAssemblyLoader(Assembly assembly, ImmutableAssemblyCacheEntry cacheEntry, ObjectItemLoadingSessionData sessionData)
|
||||
: base(assembly, cacheEntry, sessionData)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void AddToAssembliesLoaded()
|
||||
{
|
||||
// wasn't loaded, was pulled from cache instead
|
||||
// so don't load it
|
||||
}
|
||||
|
||||
|
||||
protected override void LoadTypesFromAssembly()
|
||||
{
|
||||
foreach (EdmType type in CacheEntry.TypesInAssembly)
|
||||
{
|
||||
if (!SessionData.TypesInLoading.ContainsKey(type.Identity))
|
||||
{
|
||||
SessionData.TypesInLoading.Add(type.Identity, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
//---------------------------------------------------------------------
|
||||
// <copyright file="ObjectItemNoOpAssemblyLoader.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//
|
||||
// @owner [....]
|
||||
// @backupOwner [....]
|
||||
//---------------------------------------------------------------------
|
||||
using System.Reflection;
|
||||
|
||||
namespace System.Data.Metadata.Edm
|
||||
{
|
||||
internal class ObjectItemNoOpAssemblyLoader : ObjectItemAssemblyLoader
|
||||
{
|
||||
internal ObjectItemNoOpAssemblyLoader(Assembly assembly, ObjectItemLoadingSessionData sessionData)
|
||||
: base(assembly, new MutableAssemblyCacheEntry(), sessionData)
|
||||
{ }
|
||||
|
||||
internal override void Load()
|
||||
{
|
||||
// don't do anything but make sure we know we have seen this assembly
|
||||
if (!SessionData.KnownAssemblies.Contains(SourceAssembly, SessionData.ObjectItemAssemblyLoaderFactory, SessionData.EdmItemCollection))
|
||||
{
|
||||
AddToKnownAssemblies();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void AddToAssembliesLoaded()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override void LoadTypesFromAssembly()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user