/// <summary> /// Loads the carrier dictionary from the specified assembly. /// </summary> /// <param name="assembly">The assembly to consider.</param> /// <param name="extensionDefinition">The extension definition to consider.</param> /// <param name="log">The log to consider.</param> /// <returns></returns> private int LoadCarrierDictionaryFromAssembly( Assembly assembly, IBdoExtensionDefinition extensionDefinition, IBdoLog log = null) { if (assembly == null) { return(-1); } // we load the carrier dictionary from the assembly IBdoCarrierDictionaryDto dictionaryDto = (IBdoCarrierDictionaryDto)ExtractDictionaryFromAssembly <BdoCarrierDefinitionDto>(assembly, log); // we feach carrier classes var types = assembly.GetTypes().Where(p => typeof(IBdoCarrier).IsAssignableFrom(p) && !p.IsAbstract); int count = 0; foreach (Type type in types) { IBdoCarrierDefinitionDto definitionDto = new BdoCarrierDefinitionDto(); // we update definition from carrier attribute if (type.GetCustomAttribute(typeof(BdoCarrierAttribute)) is BdoCarrierAttribute carrierAttribute) { UpdateDictionary(definitionDto, carrierAttribute); } definitionDto.ItemClass = type.FullName; definitionDto.LibraryId = extensionDefinition?.Dto?.Id; // we create the detail specification from detail property attributes foreach (PropertyInfo property in type.GetProperties().Where(p => p.GetCustomAttributes(typeof(DetailPropertyAttribute)).Any())) { definitionDto.DetailSpec.Add(ElementSpecFactory.Create(property.Name, property.PropertyType)); } // we build the runtime definition IBdoCarrierDefinition itemDefinition = new BdoCarrierDefinition(extensionDefinition, definitionDto) { RuntimeType = type }; if (dictionaryDto != null) { // retrieve the definition index // update definition with index } _store.Add <IBdoCarrierDefinition>(itemDefinition); count++; } return(count); }
/// <summary> /// Extract extension definition from the specified assembly. /// </summary> /// <param name="assembly">The assembly to consider.</param> /// <param name="resourceFullName">The full name of the resouce to consider.</param> /// <param name="log">The log to consider.</param> /// <returns>The created library.</returns> private IBdoExtensionDefinition ExtractExtensionDefinition( Assembly assembly, string resourceFullName = null, IBdoLog log = null) { IBdoExtensionDefinition definition = null; if (assembly != null) { if (resourceFullName == null) { resourceFullName = Array.Find( assembly.GetManifestResourceNames(), p => p.EndsWith(__DefaultResourceFileName, StringComparison.OrdinalIgnoreCase)); } Stream stream = null; if (resourceFullName == null) { log?.AddError("Could not find any library definition in assembly (default named '" + __DefaultResourceFileName.ToLower() + "')"); } else { try { stream = assembly.GetManifestResourceStream(resourceFullName); if (stream == null) { log?.AddError("Could not find the library definition named '" + resourceFullName + "' in assembly"); } else { IBdoExtensionDefinitionDto definitionDto = null; XmlSerializer serializer = new XmlSerializer(typeof(BdoExtensionDefinitionDto)); definitionDto = (BdoExtensionDefinitionDto)serializer.Deserialize(stream); definitionDto?.Initialize(); definition = new BdoExtensionDefinition(definitionDto); } } catch (Exception ex) { log?.AddException(ex); } finally { stream?.Close(); } } } return(definition); }
/// <summary> /// Loads the routine dictionary from the specified assembly. /// </summary> /// <param name="assembly">The assembly to consider.</param> /// <param name="extensionDefinition">The extension definition to consider.</param> /// <param name="log">The log to consider.</param> /// <returns></returns> private int LoadRoutineDictionaryFromAssembly( Assembly assembly, IBdoExtensionDefinition extensionDefinition, IBdoLog log = null) { if (assembly == null) { return(-1); } // we feach routine classes int count = 0; return(count); }
/// <summary> /// Loads the extension dictionary of the specified kind from the specified assembly. /// </summary> /// <param name="assembly">The assembly to consider.</param> /// <param name="kind">The kind of item to consider.</param> /// <param name="extensionDefinition">The extension definition to consider.</param> /// <param name="log">The log to consider.</param> /// <returns></returns> private int LoadDictionary( Assembly assembly, BdoExtensionItemKind kind, IBdoExtensionDefinition extensionDefinition = null, IBdoLog log = null) { if (assembly == null) { return(-1); } switch (kind) { case BdoExtensionItemKind.Carrier: return(LoadCarrierDictionaryFromAssembly(assembly, extensionDefinition, log)); case BdoExtensionItemKind.Connector: return(LoadConnectorDictionaryFromAssembly(assembly, extensionDefinition, log)); case BdoExtensionItemKind.Entity: return(LoadEntityDictionaryFromAssembly(assembly, extensionDefinition, log)); case BdoExtensionItemKind.Format: return(LoadFormatDictionaryFromAssembly(assembly, extensionDefinition, log)); case BdoExtensionItemKind.Handler: return(LoadHandlerDictionaryFromAssembly(assembly, extensionDefinition, log)); case BdoExtensionItemKind.Metrics: return(LoadMetricsDictionaryFromAssembly(assembly, extensionDefinition, log)); case BdoExtensionItemKind.Routine: return(LoadRoutineDictionaryFromAssembly(assembly, extensionDefinition, log)); case BdoExtensionItemKind.Scriptword: return(LoadScripwordDictionaryFromAssembly(assembly, extensionDefinition, log)); case BdoExtensionItemKind.Task: return(LoadTaskDictionaryFromAssembly(assembly, extensionDefinition, log)); case BdoExtensionItemKind.Any: case BdoExtensionItemKind.None: break; } return(-1); }
/// <summary> /// Loads the script word dictionary from the specified assembly. /// </summary> /// <param name="assembly">The assembly to consider.</param> /// <param name="extensionDefinition">The extension definition to consider.</param> /// <param name="log">The log to consider.</param> /// <returns></returns> private int LoadScripwordDictionaryFromAssembly( Assembly assembly, IBdoExtensionDefinition extensionDefinition, IBdoLog log = null) { if (assembly == null) { return(-1); } // we load the carrier dictionary from the assembly IBdoScriptwordDictionaryDto dictionaryDto = (IBdoScriptwordDictionaryDto)ExtractDictionaryFromAssembly <BdoScriptwordDefinitionDto>(assembly, log); // we define definitions int count = 0; if (dictionaryDto == null) { log?.AddWarning(title: "No script word dictionary was found"); } else { List <BdoScriptwordDefinition> scriptwordDefinitions = new List <BdoScriptwordDefinition>(); var types = assembly.GetTypes().Where(p => p.GetCustomAttributes(typeof(BdoScriptwordDefinitionAttribute)).Any()); foreach (Type type in types) { // we feach methods var methodInfos = type.GetMethods(BindingFlags.Public | BindingFlags.Static); foreach (MethodInfo methodInfo in methodInfos) { if (methodInfo.GetCustomAttribute(typeof(BdoScriptwordAttribute)) is BdoScriptwordAttribute scriptWordAttribute) { // we determine the name of the definition string definitionName = scriptWordAttribute.Name; // we update the definition with the dictionary if there is one if (dictionaryDto != null) { IBdoScriptwordDefinitionDto definitionDto = dictionaryDto.GetDefinition(definitionName, methodInfo.Name); if (definitionDto == null) { log?.AddError(title: "Script word '" + methodInfo.Name + "' not found in dictionary"); } else { definitionDto.CallingClass = type.FullName; definitionDto.LibraryId = extensionDefinition?.Dto?.Id; // we create the runtime definition BdoScriptwordDefinition itemDefinition = new BdoScriptwordDefinition(extensionDefinition, definitionDto); try { if (methodInfo.GetParameters().Length == 0) { itemDefinition.RuntimeBasicFunction += methodInfo.CreateDelegate( typeof(BdoScriptwordBasicDelegare)) as BdoScriptwordBasicDelegare; } else { itemDefinition.RuntimeScopedFunction += methodInfo.CreateDelegate( typeof(BdoScriptwordScopedDelegate)) as BdoScriptwordScopedDelegate; } scriptwordDefinitions.Add(itemDefinition); count++; } catch (ArgumentException) { log?.AddError( title: "Incompatible function ('" + methodInfo.Name + "')", description: "Function '" + definitionDto.RuntimeFunctionName + "' in class '" + definitionDto.CallingClass + "' has inexpected parameters."); } } } } } } // we build the script word tree BuildScriptwordTree(dictionaryDto, scriptwordDefinitions, log); } return(count); }
/// <summary> /// Loads the task dictionary from the specified assembly. /// </summary> /// <param name="assembly">The assembly to consider.</param> /// <param name="extensionDefinition">The extension definition to consider.</param> /// <param name="log">The log to consider.</param> /// <returns></returns> private int LoadTaskDictionaryFromAssembly( Assembly assembly, IBdoExtensionDefinition extensionDefinition, IBdoLog log = null) { if (assembly == null) { return(-1); } // we load the carrier dictionary from the assembly IBdoTaskDictionaryDto dictionaryDto = (IBdoTaskDictionaryDto)ExtractDictionaryFromAssembly <BdoTaskDefinitionDto>(assembly, log); // we feach task classes int count = 0; var types = assembly.GetTypes().Where(p => typeof(IBdoTask).IsAssignableFrom(p)); foreach (Type type in types) { IBdoTaskDefinitionDto definitionDto = new BdoTaskDefinitionDto(); if (type.GetCustomAttributes(typeof(BdoTaskAttribute)).FirstOrDefault() is BdoTaskAttribute taskAttribute) { UpdateDictionary(definitionDto, taskAttribute); } definitionDto.ItemClass = type.FullName; definitionDto.LibraryId = extensionDefinition?.Dto?.Id; foreach (PropertyInfo property in type.GetProperties().Where(p => p.GetCustomAttributes(typeof(TaskInputAttribute)).Any())) { definitionDto.InputSpecification.Add(ElementSpecFactory.Create(property.Name, property.PropertyType)); } foreach (PropertyInfo property in type.GetProperties().Where(p => p.GetCustomAttributes(typeof(TaskOutputAttribute)).Any())) { definitionDto.OutputSpecification.Add(ElementSpecFactory.Create(property.Name, property.PropertyType)); } // we build the runtime definition IBdoTaskDefinition itemDefinition = new BdoTaskDefinition(extensionDefinition, definitionDto) { RuntimeType = type }; if (dictionaryDto != null) { // retrieve the definition index // update definition with index } _store.Add <IBdoTaskDefinition>(itemDefinition); count++; } return(count); }
/// <summary> /// Loads the specified library. /// </summary> /// <param name="libraryReference">The library reference to consider.</param> /// <returns>Returns the loaded library.</returns> private IBdoLog LoadLibrary(IBdoAssemblyReference libraryReference) { var log = new BdoLog(); if (libraryReference != null && _loadOptions?.SourceKinds != null) { try { Assembly assembly = null; // first we load the assembly IBdoLog firstLog = new BdoLog() { DisplayName = "Loading library '" + libraryReference.Name + "'" }; foreach (DatasourceKind dataSourceKind in _loadOptions?.SourceKinds) { IBdoLog subLog = firstLog.AddSubLog(title: "Loading assembly from '" + dataSourceKind.ToString() + "'", eventKind: EventKinds.Message); switch (dataSourceKind) { case DatasourceKind.Memory: if (!string.IsNullOrEmpty(libraryReference.Name)) { assembly = AppDomainPool.LoadAssembly(_appDomain, libraryReference.Name, subLog); } else { subLog?.AddWarning("File name missing"); } break; case DatasourceKind.Repository: string fileName = libraryReference.FileName; if (string.IsNullOrEmpty(fileName)) { fileName = libraryReference.Name + ".dll"; } string filePath = _loadOptions.LibraryFolderPath.EndingWith(@"\").ToPath() + fileName; if (!File.Exists(filePath)) { subLog?.AddError("Could not find the assembly file path '" + filePath + "'"); } else { assembly = AppDomainPool.LoadAssemblyFromFile(_appDomain, filePath, subLog); if (assembly == null) { subLog?.AddError("Could not load assembly '" + filePath + "'"); } else { subLog?.AddCheckpoint("Loading assembly from file '" + filePath + "'"); assembly = Assembly.LoadFrom(filePath); } } break; case DatasourceKind.RestApi: break; } if (assembly != null) { subLog?.AddMessage("Assembly loaded"); break; } } // if we have an assembly then we index library items if (assembly == null) { log?.AddSubLog(firstLog, p => p.HasErrorsOrExceptionsOrWarnings()); } else { firstLog.GetEvents(true, EventKinds.Error, EventKinds.Exception).ForEach(p => p.Kind = EventKinds.Warning); log?.AddSubLog(firstLog); // we get the extension definition IBdoExtensionDefinition extensionDefinition = ExtractExtensionDefinition(assembly, null, log); // we load the using assemblies if (extensionDefinition?.Dto?.UsingAssemblyFileNames != null) { foreach (var st in extensionDefinition.Dto.UsingAssemblyFileNames) { var fileName = st; if (!fileName.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)) { fileName += ".dll"; } IBdoAssemblyReference reference = BdoAssemblyReferenceFactory.Create(st).WithFileName(fileName); log.AddSubLog(LoadExtensionsInStore(reference), title: "Loading using extensions..."); } } // we load the item definition specifiying the extension definition foreach (BdoExtensionItemKind kind in new[] { BdoExtensionItemKind.Carrier, BdoExtensionItemKind.Connector, BdoExtensionItemKind.Entity, BdoExtensionItemKind.Handler, BdoExtensionItemKind.Metrics, BdoExtensionItemKind.Routine, BdoExtensionItemKind.Scriptword, BdoExtensionItemKind.Task }) { IBdoLog subSubLog = new BdoLog(); int count = LoadDictionary(assembly, kind, extensionDefinition, subSubLog); if (subSubLog.HasErrorsOrExceptionsOrWarnings()) { log.AddSubLog( subSubLog, title: "Dictionary '" + kind.ToString() + "' loaded (" + count.ToString() + " items added)"); } else { log.AddMessage("Dictionary '" + kind.ToString() + "' loaded (" + count.ToString() + " items added)"); } } } } catch (Exception exception) { log?.AddException(exception); } } return(log); }