private static string WriteExtenders(PropertyInfo p, out bool isValidatable) { isValidatable = false; StringBuilder sb = new StringBuilder(); sb.Append(".extend({ editState : false, disableValidation : false, empty : true })"); RequiredAttribute requiredAttribute = p.GetCustomAttribute <RequiredAttribute>(); if (requiredAttribute != null) { sb.Append($".extend({{ required: {{ message: \"{requiredAttribute.FormatErrorMessage(p.Name)}\", onlyIf: function() {{ return ko.utils.isPropertyValidatable(self, \"{ p.Name}\"); }} }} }})"); isValidatable = true; } MinLengthAttribute minLengthAttribute = p.GetCustomAttribute <MinLengthAttribute>(); if (minLengthAttribute != null) { sb.Append(string.Format(".extend({ minLength: { message: \"{0}\", params: {1}, onlyIf: function() { return ko.utils.isPropertyValidatable(self, \"{2}\"); } } })", minLengthAttribute.FormatErrorMessage(p.Name), minLengthAttribute.Length, p.Name)); isValidatable = true; } MaxLengthAttribute maxLengthAttribute = p.GetCustomAttribute <MaxLengthAttribute>(); if (maxLengthAttribute != null) { sb.Append(string.Format(".extend({ maxLength: { message: \"{0}\", params: {1}, onlyIf: function() { return ko.utils.isPropertyValidatable(self, \"{2}\"); } } })", maxLengthAttribute.FormatErrorMessage(p.Name), maxLengthAttribute.Length, p.Name)); isValidatable = true; } RegularExpressionAttribute regularExpressionAttribute = p.GetCustomAttribute <RegularExpressionAttribute>(); if (regularExpressionAttribute != null) { sb.Append(string.Format(".extend({ pattern: { message: \"{0}\", params: /{1}/, onlyIf: function() { return ko.utils.isPropertyValidatable(self, \"{2}\"); } } })", regularExpressionAttribute.FormatErrorMessage(p.Name), regularExpressionAttribute.Pattern, p.Name)); isValidatable = true; } UrlAttribute urlAttribute = p.GetCustomAttribute <UrlAttribute>(); if (urlAttribute != null) { sb.Append(string.Format(".extend({ pattern: { message: \"{0}\", params: /{1}/, onlyIf: function() { return ko.utils.isPropertyValidatable(self, \"{2}\"); } } })", urlAttribute.FormatErrorMessage(p.Name), urlAttribute, p.Name)); isValidatable = true; } DateAttribute dateAttribute = p.GetCustomAttribute <DateAttribute>(); if (dateAttribute != null) { sb.Append(string.Format(".extend({ date: { message: \"{0}\", onlyIf: function() { return ko.utils.isPropertyValidatable(self, \"{1}\"); } } })", dateAttribute.FormatErrorMessage(p.Name), p.Name)); isValidatable = true; } NumericAttribute numericAttribute = p.GetCustomAttribute <NumericAttribute>(); if (numericAttribute != null) { sb.Append( string.Format(".extend({ number: { message: \"{0}\", onlyIf: function() { return ko.utils.isPropertyValidatable(self, \"{1}\"); } } }).extend({ numeric: {2} })", numericAttribute.FormatErrorMessage(p.Name), p.Name, numericAttribute.Precision)); isValidatable = true; } EmailAttribute emailAttribute = p.GetCustomAttribute <EmailAttribute>(); if (emailAttribute != null) { sb.Append(string.Format(".extend({ email: { message: \"{0}\", onlyIf: function() { return ko.utils.isPropertyValidatable(self, \"{1}\"); } } })", emailAttribute.FormatErrorMessage(p.Name), p.Name)); isValidatable = true; } DigitsAttribute digitsAttribute = p.GetCustomAttribute <DigitsAttribute>(); if (digitsAttribute != null) { sb.Append(string.Format(".extend({ digit: { message: \"{0}\", onlyIf: function() { return ko.utils.isPropertyValidatable(self, \"{1}\"); } } }).extend({ numeric: 0 })", digitsAttribute.FormatErrorMessage(p.Name), p.Name)); isValidatable = true; } MinAttribute minAttribute = p.GetCustomAttribute <MinAttribute>(); if (minAttribute != null) { sb.Append(string.Format(".extend({ min: { message: \"{0}\", params: {1}, onlyIf: function() { return ko.utils.isPropertyValidatable(self, \"{2}\"); } } })", minAttribute.FormatErrorMessage(p.Name), minAttribute.Min, p.Name)); isValidatable = true; } MaxAttribute maxAttribute = p.GetCustomAttribute <MaxAttribute>(); if (maxAttribute != null) { sb.Append(string.Format(".extend({ max: { message: \"{0}\", params: {1}, onlyIf: function() { return ko.utils.isPropertyValidatable(self, \"{2}\"); } } })", maxAttribute.FormatErrorMessage(p.Name), maxAttribute.Max, p.Name)); isValidatable = true; } EqualToAttribute equalToAttribute = p.GetCustomAttribute <EqualToAttribute>(); if (equalToAttribute != null) { sb.Append(string.Format(".extend({ equal: { message: \"{0}\", params: {1}, onlyIf: function() { return ko.utils.isPropertyValidatable(self, \"{2}\"); } } })", equalToAttribute.FormatErrorMessage(p.Name), equalToAttribute.OtherProperty, p.Name)); isValidatable = true; } CompareAttribute compareAttribute = p.GetCustomAttribute <CompareAttribute>(); if (compareAttribute != null) { sb.Append(string.Format(".extend({ equal: { message: \"{0}\", params: \"{1}\", onlyIf: function() { return ko.utils.isPropertyValidatable(self, \"{2}\"); } } })", compareAttribute.FormatErrorMessage(p.Name), compareAttribute.OtherProperty, p.Name)); isValidatable = true; } FormatterAttribute formatterAttribute = p.GetCustomAttribute <FormatterAttribute>(); if (formatterAttribute != null) { sb.Append(string.Format(".formatted({0}, {1})", formatterAttribute.Formatter, JsonConvert.SerializeObject(formatterAttribute.Arguments))); } return(sb.ToString()); }
/// <summary> /// 加载 DLL 插件。 /// </summary> /// <param name="dllFiles">DLL 插件列表。</param> private void LoadDllPlugins(string[] dllFiles) { foreach (string file in dllFiles) { try { _logger.LogDebug($"Loading plugin: {file}"); Assembly pluginAssembly = LoadPlugin(file); Type[] exportedTypes = pluginAssembly.GetExportedTypes(); string pluginName = pluginAssembly.FullName; _logger.LogDebug($"Parsing meta in plugin: {pluginName}"); Type[] metaTypes = exportedTypes.Where(type => Attribute.GetCustomAttribute(type, typeof(RmboxPluginAttribute)) is not null).ToArray(); if (metaTypes.Length != 1) { string err = $"插件 {pluginName} 具有的元信息的个数 {metaTypes.Length} 不符合 1 的要求。"; _logger.LogError(err); throw new IndexOutOfRangeException(err); } // ReSharper disable once UseNegatedPatternMatching IMeta pluginMeta = Activator.CreateInstance(metaTypes.Single()) as IMeta; if (pluginMeta is null) { string err = $"在加载插件 {pluginName} 的元信息时发生错误。"; _logger.LogError(err); throw new ArgumentNullException(nameof(pluginMeta)); } _logger.LogDebug($"Meta parsed in: {pluginMeta.Name}"); MetaCollection.Add((pluginMeta, pluginAssembly)); _logger.LogDebug($"Parsing components in plugin: {pluginMeta.Name}"); List <Type> operationTypes = exportedTypes.Where(type => Attribute.GetCustomAttribute(type, typeof(OperationAttribute)) is not null).ToList(); foreach (Type t in operationTypes.Where(type => !type.IsAssignableTo(typeof(IOperation))) .ToArray()) { _logger.LogWarning($"检测到错误导出的类型 {t.FullName},将会忽略加载。"); operationTypes.Remove(t); } foreach (Type operationType in operationTypes) { OperationAttribute operationAttribute = Attribute.GetCustomAttribute(operationType, typeof(OperationAttribute)) as OperationAttribute; OperationCollection.Add((operationAttribute, pluginMeta, operationType)); _logger.LogDebug($"Operation {operationAttribute.Name} loaded."); } List <Type> configSectionTypes = exportedTypes.Where(type => Attribute.GetCustomAttribute(type, typeof(ConfigSectionAttribute)) is not null).ToList(); foreach (Type t in configSectionTypes.Where(type => !type.IsSubclassOf(typeof(ConfigSectionBase))) .ToArray()) { _logger.LogWarning($"检测到错误导出的类型 {t.FullName},将会忽略加载。"); configSectionTypes.Remove(t); } foreach (Type configSectionType in configSectionTypes) { var configSectionAttribute = Attribute.GetCustomAttribute(configSectionType, typeof(ConfigSectionAttribute)) as ConfigSectionAttribute; ConfigSectionCollection.Add((configSectionAttribute, configSectionType)); _logger.LogDebug($"Config section {configSectionAttribute.Id} loaded."); } List <Type> formatterTypes = exportedTypes.Where(type => Attribute.GetCustomAttribute(type, typeof(FormatterAttribute)) is not null).ToList(); foreach (Type t in formatterTypes.Where(type => !type.IsAssignableTo(typeof(IFormatter))) .ToArray()) { _logger.LogWarning($"检测到错误导出的类型 {t.FullName},将会忽略加载。"); formatterTypes.Remove(t); } foreach (Type formatterType in formatterTypes) { FormatterAttribute formatterAttribute = Attribute.GetCustomAttribute(formatterType, typeof(FormatterAttribute)) as FormatterAttribute; FormatterCollection.Add((formatterAttribute, formatterType)); _logger.LogDebug($"Formatter {formatterType.FullName} loaded."); } _logger.LogDebug($"Plugin {pluginMeta.Name} loaded."); } catch (Exception e) { _logger.LogWarning(e, $"在加载插件 {file} 时发生错误。将跳过该插件的加载。"); } } }