public static Dictionary<IMethod, Dictionary<string,List<KeyValuePair<INode,IMethodOrProperty>>>> externalMethodsAndProperties(this O2MappedAstData astData, string filter, string targetFolder, int numberOfItemsToProcess)
        {
        	var MimimumAvailableMemoryRequired = "".availableMemory()/4; //50;
        	"Starting externalMethodsAndProperties calculations (with min memory required set to: {0}".info(MimimumAvailableMemoryRequired);
        	if (targetFolder.valid().isFalse())
        		targetFolder = PublicDI.config.getTempFolderInTempDirectory("_AstEngine_ExternalMappings"); 
        	
        	var methodMappingHashesFile = targetFolder.pathCombine("_methodMappingHashes.txt");
        	        
        	var o2Timer = new O2Timer("Calculated externalMethodsAndProperties").start();
        	var iMethodMappings = new Dictionary<IMethod, Dictionary<string,List<KeyValuePair<INode,IMethodOrProperty>>>>(); 					
        	var iMethods = astData.iMethods();
        	var itemsToMap = iMethods.size();// - targetFolder.files().size();
			var itemsMapped = 0;
								
			foreach(var iMethod in iMethods)
			{
				// check avaialble memory
				var availableMemory = new System.Diagnostics.PerformanceCounter("Memory", "Available MBytes").NextValue();
				if (availableMemory < MimimumAvailableMemoryRequired)
				{
					"In externalMethodsAndProperties, There is not enough free memory to continue (MimimumAvailableMemoryRequired = {0}, availableMemory = {1}. Stopping mappings".error(MimimumAvailableMemoryRequired,availableMemory);
					"There are {0} iMethodMappings".debug(iMethodMappings.size());
					break;
				}
				//"Available Memory: {0}".debug(availableMemory);
				
				//convert method
				var fullName = iMethod.fullName();
                var md5Hash = fullName.safeFileName().md5Hash();
                var savedMethodMappingsFile = targetFolder.pathCombine(md5Hash) + ".xml";
				//var savedMethodMappingsFile = targetFolder.pathCombine(iMethod.fullName().safeFileName(100))+ ".xml";
				itemsMapped++;
				if (savedMethodMappingsFile.fileExists().isFalse()) // Skip if method mappings have already been calculated
				{
					//"Mapping :{0}".debug(iMethod.DotNetName);
					if (iMethod.Name.regEx(filter))	
					{
						var mappings = astData.externalMethodsAndProperties(iMethod);
						iMethodMappings.Add(iMethod, mappings);
						var savedMethodMappings = astData.saveMappings(mappings);
						if (savedMethodMappings.fileExists())
						{	
							Files.MoveFile(savedMethodMappings, savedMethodMappingsFile);
							methodMappingHashesFile.fileInsertAt(0,"{0}\t{1}".format(md5Hash, fullName).line());
						}
						
					}
						//savedMethodMappingsFile	
					if (itemsMapped % 10 ==0)		// every 10 methods show a log message		
					{
						"In externalMethodsAndProperties, mapped [{0}/{1}] to folder: {2}".info(itemsMapped, itemsToMap, targetFolder);
						if (itemsMapped % 100 ==0)	
							PublicDI.config.gcCollect();	// every 100 methods release some memory				
					}
					if (numberOfItemsToProcess > 0 && numberOfItemsToProcess < iMethodMappings.size())
					{
						"In externalMethodsAndProperties, max number of Items To Process reached ({0}), so stopping mappings]".info(numberOfItemsToProcess);
						"There are {0} iMethodMappings".debug(iMethodMappings.size());
						break;
					}												
				}
			}
			o2Timer.stop();
			return iMethodMappings;
		}
        public static Assembly loadAssemblyAndAllItsDependencies(this string pathToAssemblyToLoad)
        {
            var referencesFolder = pathToAssemblyToLoad.directoryName();
            var referencesFiles = referencesFolder.files(true,"*.dll", "*.exe");

            Func<string,string> resolveAssemblyName =
                (name)=>{
                            if (name.starts("System"))
                                return name;
                            if (name.isAssemblyName())
                                name = name.assembly_Name();

                            var resolvedPath = referencesFiles.find_File_in_List(name, name+ ".dll", name+ ".exe");

                            if(resolvedPath.fileExists())
                            {
                                //"**** Found match:{0}".info(resolvedPath);
                                return resolvedPath;
                            }

                            //"**** Couldn't match:{0}".error(resolvedPath);
                            return null;
                };

            var loadedAssemblies = new Dictionary<string, Assembly>();
            // ReSharper disable ImplicitlyCapturedClosure
            // ReSharper disable AccessToModifiedClosure
            Action<Assembly> loadReferencedAssemblies = (assembly) => { };
            Func<string, Assembly> loadAssembly = null;
            loadAssembly =
                (assemblyPathOrName) => {
                                            if (loadedAssemblies.hasKey(assemblyPathOrName))
                                                return loadedAssemblies[assemblyPathOrName];
                                            var assembly = assemblyPathOrName.resolveAssembly(resolveAssemblyName);
                                            if(assembly.notNull())
                                            {
                                                loadedAssemblies.add(assemblyPathOrName, assembly);
                                                loadReferencedAssemblies(assembly);
                                                if (assembly.Location.valid().isFalse())
                                                {
                                                    loadAssembly(assembly.FullName.assembly_Name());
                                                    loadAssembly(assembly.ManifestModule.Name != "<Unknown>"
                                                                     ? assembly.ManifestModule.Name
                                                                     : assembly.ManifestModule.ScopeName);
                                                }
                                                //loadAssembly(assembly.ManifestModule.Name);

                                            }
                                            return assembly;
                };

            loadReferencedAssemblies =
                (assembly)=>{
                                var referencedAssemblies =  assembly.referencedAssemblies();
                                foreach(var referencedAssembly in referencedAssemblies)
                                {
                                    var assemblyName = referencedAssembly.str();
                                    if (loadAssembly(assemblyName).isNull())
                                        "COULD NOT LOAD Referenced Assembly: {0}".error(assemblyName);
                                }
                };
            // ReSharper restore ImplicitlyCapturedClosure
            // ReSharper restore AccessToModifiedClosure
            var mainAssembly = loadAssembly(pathToAssemblyToLoad);

            "[loadAssemblyAndAllItsDependencies] there were {0} references loaded/mapped from '{1}'".info(loadedAssemblies.size(), pathToAssemblyToLoad);
            //show.info(loadedAssemblies);

            return mainAssembly;
        }