/// <summary> /// Returns a unique hash for the combination of FileInfo objects passed in /// </summary> /// <param name="filesAndFolders"></param> /// <returns></returns> internal static long GetAssembliesHash(IEnumerable <FileSystemInfo> filesAndFolders) { using (DisposableTimer.TraceDuration <PluginManager>("Determining hash of code files on disk", "Hash determined")) { var hashCombiner = new HashCodeCombiner(); //add each unique folder to the hash foreach (var i in filesAndFolders.DistinctBy(x => x.FullName)) { hashCombiner.AddFileSystemItem(i); } return(ConvertPluginsHashFromHex(hashCombiner.GetCombinedHashCode())); } }
private IEnumerable <Type> ResolveTypes <T>( Func <IEnumerable <Type> > finder, TypeResolutionKind resolutionType, bool cacheResult) { using (var readLock = new UpgradeableReadLock(_lock)) { using (DisposableTimer.TraceDuration <PluginManager>( String.Format("Starting resolution types of {0}", typeof(T).FullName), String.Format("Completed resolution of types of {0}", typeof(T).FullName))) { //check if the TypeList already exists, if so return it, if not we'll create it var typeList = _types.SingleOrDefault(x => x.IsTypeList <T>(resolutionType)); //if we're not caching the result then proceed, or if the type list doesn't exist then proceed if (!cacheResult || typeList == null) { //upgrade to a write lock since we're adding to the collection readLock.UpgradeToWriteLock(); typeList = new TypeList <T>(resolutionType); foreach (var t in finder()) { typeList.AddType(t); } //only add the cache if we are to cache the results if (cacheResult) { //add the type list to the collection _types.Add(typeList); } } return(typeList.GetTypes()); } } }
private IEnumerable <Type> ResolveTypes <T>( Func <IEnumerable <Type> > finder, TypeResolutionKind resolutionType, bool cacheResult) { using (var readLock = new UpgradeableReadLock(_lock)) { var typesFound = new List <Type>(); using (DisposableTimer.TraceDuration <PluginManager>( () => String.Format("Starting resolution types of {0}", typeof(T).FullName), () => String.Format("Completed resolution of types of {0}, found {1}", typeof(T).FullName, typesFound.Count))) { //check if the TypeList already exists, if so return it, if not we'll create it var typeList = _types.SingleOrDefault(x => x.IsTypeList <T>(resolutionType)); //if we're not caching the result then proceed, or if the type list doesn't exist then proceed if (!cacheResult || typeList == null) { //upgrade to a write lock since we're adding to the collection readLock.UpgradeToWriteLock(); typeList = new TypeList <T>(resolutionType); //we first need to look into our cache file (this has nothing to do with the 'cacheResult' parameter which caches in memory). //if assemblies have not changed and the cache file actually exists, then proceed to try to lookup by the cache file. if (!HaveAssembliesChanged && File.Exists(GetPluginListFilePath())) { var fileCacheResult = TryGetCachedPluginsFromFile <T>(resolutionType); //here we need to identify if the CachedPluginNotFoundInFile was the exception, if it was then we need to re-scan //in some cases the plugin will not have been scanned for on application startup, but the assemblies haven't changed //so in this instance there will never be a result. if (fileCacheResult.Error != null && fileCacheResult.Error is CachedPluginNotFoundInFile) { //we don't have a cache for this so proceed to look them up by scanning LoadViaScanningAndUpdateCacheFile <T>(typeList, resolutionType, finder); } else { if (fileCacheResult.Success) { var successfullyLoadedFromCache = true; //we have a previous cache for this so we don't need to scan we just load what has been found in the file foreach (var t in fileCacheResult.Result) { try { //we use the build manager to ensure we get all types loaded, this is slightly slower than //Type.GetType but if the types in the assembly aren't loaded yet then we have problems with that. var type = BuildManager.GetType(t, true); typeList.AddType(type); } catch (Exception ex) { //if there are any exceptions loading types, we have to exist, this should never happen so //we will need to revert to scanning for types. successfullyLoadedFromCache = false; LogHelper.Error <PluginManager>("Could not load a cached plugin type: " + t + " now reverting to re-scanning assemblies for the base type: " + typeof(T).FullName, ex); break; } } if (!successfullyLoadedFromCache) { //we need to manually load by scanning if loading from the file was not successful. LoadViaScanningAndUpdateCacheFile <T>(typeList, resolutionType, finder); } else { LogHelper.Debug <PluginManager>("Loaded plugin types " + typeof(T).FullName + " from persisted cache"); } } } } else { //we don't have a cache for this so proceed to look them up by scanning LoadViaScanningAndUpdateCacheFile <T>(typeList, resolutionType, finder); } //only add the cache if we are to cache the results if (cacheResult) { //add the type list to the collection _types.Add(typeList); } } typesFound = typeList.GetTypes().ToList(); } return(typesFound); } }