Example #1
0
        /// <summary>
        /// This method will return the data type descriptor for the given data type id.
        /// If the data type descriptor has not yet been created (file not existing) and
        /// the <paramref name="allowDataTypeCreation"/> is set to true,
        /// this method will try getting it through the <see cref="Composite.Data.DynamicTypes.Foundation.ReflectionBasedDescriptorBuilder"/>
        /// that will try locating the type from the data type id using refelction
        /// going through know assemblies.
        /// </summary>
        /// <param name="dataTypeId">The id of the data type.</param>
        /// <param name="allowDataTypeCreation">
        /// If this is true and the data type descriptor does not exists, it will try to
        /// be created.
        /// </param>
        /// <returns></returns>
        public static DataTypeDescriptor GetDataTypeDescriptor(Guid dataTypeId, bool allowDataTypeCreation = false)
        {
            Initialize();

            DataTypeDescriptor dataTypeDescriptor;

            _dataTypeDescriptorCache.TryGetValue(dataTypeId, out dataTypeDescriptor);

            if (dataTypeDescriptor != null)
            {
                return(dataTypeDescriptor);
            }


            if (!allowDataTypeCreation)
            {
                return(null);
            }

            foreach (Assembly assembly in AssemblyFacade.GetLoadedAssembliesFromBin())
            {
                if (!AssemblyFacade.AssemblyPotentiallyUsesType(assembly, typeof(IData)))
                {
                    // Ignoring assemblies that aren't referencing Composite.dll
                    continue;
                }

                Type[] types;
                try
                {
                    types = assembly.GetTypes();
                }
                catch (ReflectionTypeLoadException ex)
                {
                    throw new InvalidOperationException($"Failed to get types from assembly '{assembly.FullName}'", ex);
                }

                foreach (Type type in types)
                {
                    if (type.GetInterfaces().Contains(typeof(IData)))
                    {
                        ImmutableTypeIdAttribute attribute = type.GetCustomAttributes(false).OfType <ImmutableTypeIdAttribute>().SingleOrDefault();
                        if (attribute == null || attribute.ImmutableTypeId != dataTypeId)
                        {
                            continue;
                        }

                        DataTypeDescriptor newDataTypeDescriptor = ReflectionBasedDescriptorBuilder.Build(type);
                        PersistMetaData(newDataTypeDescriptor);

                        return(newDataTypeDescriptor);
                    }
                }
            }


            Log.LogError(LogTitle, $"No data type found with the given data type id '{dataTypeId}'");

            return(null);
        }
Example #2
0
        /// <summary>
        /// Call this method whan a new assembly is load/added into the app domain.
        /// </summary>
        /// <param name="assembly"></param>
        /// <param name="logTypeLoadErrors"></param>
        public static void AddNewAssembly(Assembly assembly, bool logTypeLoadErrors)
        {
            if (!AssemblyFacade.AssemblyPotentiallyUsesType(assembly, typeof(IData)))
            {
                return;
            }

            try
            {
                var types = assembly.GetTypes();

                _LoadedDataTypes.AddRange(types.Where(typeof(IData).IsAssignableFrom));
            }
            catch (ReflectionTypeLoadException exception)
            {
                if (logTypeLoadErrors)
                {
                    var exceptionToLog = exception.LoaderExceptions != null?exception.LoaderExceptions.First() : exception;

                    Log.LogError(LogTitle, new Exception($"Failed to load assembly '{assembly.FullName}'", exceptionToLog));
                }
            }
        }
        private static StartupHandlerInfo[] GetSubscribedTypes(
            string filePath, List <AssemblyInfo> cachedTypesInfo, ref bool cacheHasBeenUpdated)
        {
            string assemblyName = Path.GetFileNameWithoutExtension(filePath);

            foreach (string assemblyToIgnore in AssembliesToIgnore)
            {
                if (assemblyName == assemblyToIgnore || assemblyName.StartsWith(assemblyToIgnore + ",") ||
                    (assemblyToIgnore.EndsWith(".") && assemblyName.StartsWith(assemblyToIgnore)))
                {
                    return(null);
                }
            }

            DateTime modificationDate = C1File.GetLastWriteTime(filePath);

            var cachedInfo = cachedTypesInfo.FirstOrDefault(asm => asm.AssemblyName == assemblyName);

            if (cachedInfo != null)
            {
                if (cachedInfo.LastModified == modificationDate)
                {
                    string[] subscribedTypesNames = cachedInfo.SubscribedTypes;
                    if (subscribedTypesNames.Length == 0)
                    {
                        return(new StartupHandlerInfo[0]);
                    }

                    var asm = Assembly.LoadFrom(filePath);
                    return((from typeName in subscribedTypesNames
                            let type = asm.GetType(typeName)
                                       where  type != null
                                       let attribute = type.GetCustomAttributes(false)
                                                       .OfType <ApplicationStartupAttribute>()
                                                       .FirstOrDefault()
                                                       where attribute != null
                                                       select new StartupHandlerInfo(type, attribute)).ToArray());
                }

                // Removing cache entry if it is obsolete
                cachedTypesInfo.Remove(cachedInfo);
            }

            Assembly assembly;

            try
            {
                assembly = Assembly.LoadFrom(filePath);
            }
            catch (ReflectionTypeLoadException ex)
            {
                Log.LogWarning(LogTitle, "Failed to load assembly '{0}'".FormatWith(filePath));
                if (ex.LoaderExceptions != null && ex.LoaderExceptions.Length > 0)
                {
                    Log.LogError(LogTitle, ex.LoaderExceptions[0]);
                }

                return(null);
            }

            if (!AssemblyFacade.AssemblyPotentiallyUsesType(assembly, typeof(ApplicationStartupAttribute)))
            {
                return(null);
            }

            Type[] types;

            if (!TryGetTypes(assembly, out types))
            {
                return(new StartupHandlerInfo[0]);
            }

            var result = GetSubscribedTypes(types);

            var newCacheEntry = new AssemblyInfo
            {
                AssemblyName    = assembly.GetName().Name,
                LastModified    = modificationDate,
                SubscribedTypes = result.Select(sh => sh.Type.FullName).ToArray()
            };

            cachedTypesInfo.Add(newCacheEntry);

            cacheHasBeenUpdated = true;

            return(result);
        }