diff --git a/extensions/Squidex.Extensions/Actions/Algolia/AlgoliaAction.cs b/extensions/Squidex.Extensions/Actions/Algolia/AlgoliaAction.cs index c6952b152..eb6c041a4 100644 --- a/extensions/Squidex.Extensions/Actions/Algolia/AlgoliaAction.cs +++ b/extensions/Squidex.Extensions/Actions/Algolia/AlgoliaAction.cs @@ -11,7 +11,6 @@ using Squidex.Domain.Apps.Core.Rules; namespace Squidex.Extensions.Actions.Algolia { - [RuleActionHandler(typeof(AlgoliaActionHandler))] [RuleAction( IconImage = "", IconColor = "#0d9bf9", diff --git a/extensions/Squidex.Extensions/Actions/Algolia/AlgoliaPlugin.cs b/extensions/Squidex.Extensions/Actions/Algolia/AlgoliaPlugin.cs index 71d0f4c08..9ef4538c9 100644 --- a/extensions/Squidex.Extensions/Actions/Algolia/AlgoliaPlugin.cs +++ b/extensions/Squidex.Extensions/Actions/Algolia/AlgoliaPlugin.cs @@ -7,7 +7,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Infrastructure.Plugins; namespace Squidex.Extensions.Actions.Algolia @@ -16,7 +15,7 @@ namespace Squidex.Extensions.Actions.Algolia { public void ConfigureServices(IServiceCollection services, IConfiguration configuration) { - RuleActionRegistry.Add(); + services.AddRuleAction(); } } } diff --git a/extensions/Squidex.Extensions/Actions/AzureQueue/AzureQueueAction.cs b/extensions/Squidex.Extensions/Actions/AzureQueue/AzureQueueAction.cs index 45f176d9f..41c5be7a9 100644 --- a/extensions/Squidex.Extensions/Actions/AzureQueue/AzureQueueAction.cs +++ b/extensions/Squidex.Extensions/Actions/AzureQueue/AzureQueueAction.cs @@ -14,7 +14,6 @@ using Squidex.Infrastructure; namespace Squidex.Extensions.Actions.AzureQueue { - [RuleActionHandler(typeof(AzureQueueActionHandler))] [RuleAction( IconImage = "", IconColor = "#0d9bf9", diff --git a/extensions/Squidex.Extensions/Actions/AzureQueue/AzureQueuePlugin.cs b/extensions/Squidex.Extensions/Actions/AzureQueue/AzureQueuePlugin.cs index e069c08d2..43c84e857 100644 --- a/extensions/Squidex.Extensions/Actions/AzureQueue/AzureQueuePlugin.cs +++ b/extensions/Squidex.Extensions/Actions/AzureQueue/AzureQueuePlugin.cs @@ -7,7 +7,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Infrastructure.Plugins; namespace Squidex.Extensions.Actions.AzureQueue @@ -16,7 +15,7 @@ namespace Squidex.Extensions.Actions.AzureQueue { public void ConfigureServices(IServiceCollection services, IConfiguration configuration) { - RuleActionRegistry.Add(); + services.AddRuleAction(); } } } diff --git a/extensions/Squidex.Extensions/Actions/Discourse/DiscourseAction.cs b/extensions/Squidex.Extensions/Actions/Discourse/DiscourseAction.cs index 97f6b6538..295c7f683 100644 --- a/extensions/Squidex.Extensions/Actions/Discourse/DiscourseAction.cs +++ b/extensions/Squidex.Extensions/Actions/Discourse/DiscourseAction.cs @@ -13,7 +13,6 @@ using Squidex.Infrastructure; namespace Squidex.Extensions.Actions.Discourse { - [RuleActionHandler(typeof(DiscourseActionHandler))] [RuleAction( IconImage = "", IconColor = "#eB6121", diff --git a/extensions/Squidex.Extensions/Actions/Discourse/DiscoursePlugin.cs b/extensions/Squidex.Extensions/Actions/Discourse/DiscoursePlugin.cs index 2d7d9f6d7..fb1105657 100644 --- a/extensions/Squidex.Extensions/Actions/Discourse/DiscoursePlugin.cs +++ b/extensions/Squidex.Extensions/Actions/Discourse/DiscoursePlugin.cs @@ -7,7 +7,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Infrastructure.Plugins; namespace Squidex.Extensions.Actions.Discourse @@ -16,7 +15,7 @@ namespace Squidex.Extensions.Actions.Discourse { public void ConfigureServices(IServiceCollection services, IConfiguration configuration) { - RuleActionRegistry.Add(); + services.AddRuleAction(); } } } diff --git a/extensions/Squidex.Extensions/Actions/ElasticSearch/ElasticSearchAction.cs b/extensions/Squidex.Extensions/Actions/ElasticSearch/ElasticSearchAction.cs index 00b4a74db..298e4ad66 100644 --- a/extensions/Squidex.Extensions/Actions/ElasticSearch/ElasticSearchAction.cs +++ b/extensions/Squidex.Extensions/Actions/ElasticSearch/ElasticSearchAction.cs @@ -13,7 +13,6 @@ using Squidex.Infrastructure; namespace Squidex.Extensions.Actions.ElasticSearch { - [RuleActionHandler(typeof(ElasticSearchActionHandler))] [RuleAction( IconImage = "", IconColor = "#1e5470", diff --git a/extensions/Squidex.Extensions/Actions/ElasticSearch/ElasticSearchPlugin.cs b/extensions/Squidex.Extensions/Actions/ElasticSearch/ElasticSearchPlugin.cs index 49cf06697..50bdf12d4 100644 --- a/extensions/Squidex.Extensions/Actions/ElasticSearch/ElasticSearchPlugin.cs +++ b/extensions/Squidex.Extensions/Actions/ElasticSearch/ElasticSearchPlugin.cs @@ -7,7 +7,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Infrastructure.Plugins; namespace Squidex.Extensions.Actions.ElasticSearch @@ -16,7 +15,7 @@ namespace Squidex.Extensions.Actions.ElasticSearch { public void ConfigureServices(IServiceCollection services, IConfiguration configuration) { - RuleActionRegistry.Add(); + services.AddRuleAction(); } } } diff --git a/extensions/Squidex.Extensions/Actions/Email/EmailAction.cs b/extensions/Squidex.Extensions/Actions/Email/EmailAction.cs index be24d3166..c801e629b 100644 --- a/extensions/Squidex.Extensions/Actions/Email/EmailAction.cs +++ b/extensions/Squidex.Extensions/Actions/Email/EmailAction.cs @@ -11,7 +11,6 @@ using Squidex.Domain.Apps.Core.Rules; namespace Squidex.Extensions.Actions.Email { - [RuleActionHandler(typeof(EmailActionHandler))] [RuleAction( IconImage = "", IconColor = "#333300", diff --git a/extensions/Squidex.Extensions/Actions/Email/EmailPlugin.cs b/extensions/Squidex.Extensions/Actions/Email/EmailPlugin.cs index 34a5c88ce..aeed28445 100644 --- a/extensions/Squidex.Extensions/Actions/Email/EmailPlugin.cs +++ b/extensions/Squidex.Extensions/Actions/Email/EmailPlugin.cs @@ -7,7 +7,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Infrastructure.Plugins; namespace Squidex.Extensions.Actions.Email @@ -16,7 +15,7 @@ namespace Squidex.Extensions.Actions.Email { public void ConfigureServices(IServiceCollection services, IConfiguration configuration) { - RuleActionRegistry.Add(); + services.AddRuleAction(); } } } diff --git a/extensions/Squidex.Extensions/Actions/Fastly/FastlyAction.cs b/extensions/Squidex.Extensions/Actions/Fastly/FastlyAction.cs index e4e056ba7..d227e8ce1 100644 --- a/extensions/Squidex.Extensions/Actions/Fastly/FastlyAction.cs +++ b/extensions/Squidex.Extensions/Actions/Fastly/FastlyAction.cs @@ -11,7 +11,6 @@ using Squidex.Domain.Apps.Core.Rules; namespace Squidex.Extensions.Actions.Fastly { - [RuleActionHandler(typeof(FastlyActionHandler))] [RuleAction( IconImage = "", IconColor = "#e23335", diff --git a/extensions/Squidex.Extensions/Actions/Fastly/FastlyPlugin.cs b/extensions/Squidex.Extensions/Actions/Fastly/FastlyPlugin.cs index 8268d912a..f6802dde3 100644 --- a/extensions/Squidex.Extensions/Actions/Fastly/FastlyPlugin.cs +++ b/extensions/Squidex.Extensions/Actions/Fastly/FastlyPlugin.cs @@ -7,7 +7,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Infrastructure.Plugins; namespace Squidex.Extensions.Actions.Fastly @@ -16,7 +15,7 @@ namespace Squidex.Extensions.Actions.Fastly { public void ConfigureServices(IServiceCollection services, IConfiguration configuration) { - RuleActionRegistry.Add(); + services.AddRuleAction(); } } } diff --git a/extensions/Squidex.Extensions/Actions/Medium/MediumAction.cs b/extensions/Squidex.Extensions/Actions/Medium/MediumAction.cs index 65eddcefd..3c6ce25e2 100644 --- a/extensions/Squidex.Extensions/Actions/Medium/MediumAction.cs +++ b/extensions/Squidex.Extensions/Actions/Medium/MediumAction.cs @@ -11,7 +11,6 @@ using Squidex.Domain.Apps.Core.Rules; namespace Squidex.Extensions.Actions.Medium { - [RuleActionHandler(typeof(MediumActionHandler))] [RuleAction( IconImage = "", IconColor = "#00ab6c", diff --git a/extensions/Squidex.Extensions/Actions/Medium/MediumPlugin.cs b/extensions/Squidex.Extensions/Actions/Medium/MediumPlugin.cs index 8a1090672..b2664ac3b 100644 --- a/extensions/Squidex.Extensions/Actions/Medium/MediumPlugin.cs +++ b/extensions/Squidex.Extensions/Actions/Medium/MediumPlugin.cs @@ -7,7 +7,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Infrastructure.Plugins; namespace Squidex.Extensions.Actions.Medium @@ -16,7 +15,7 @@ namespace Squidex.Extensions.Actions.Medium { public void ConfigureServices(IServiceCollection services, IConfiguration configuration) { - RuleActionRegistry.Add(); + services.AddRuleAction(); } } } diff --git a/extensions/Squidex.Extensions/Actions/Prerender/PrerenderAction.cs b/extensions/Squidex.Extensions/Actions/Prerender/PrerenderAction.cs index 0978a79a4..44285379f 100644 --- a/extensions/Squidex.Extensions/Actions/Prerender/PrerenderAction.cs +++ b/extensions/Squidex.Extensions/Actions/Prerender/PrerenderAction.cs @@ -11,7 +11,6 @@ using Squidex.Domain.Apps.Core.Rules; namespace Squidex.Extensions.Actions.Prerender { - [RuleActionHandler(typeof(PrerenderActionHandler))] [RuleAction( IconImage = "", IconColor = "#2c3e50", diff --git a/extensions/Squidex.Extensions/Actions/Prerender/PrerenderPlugin.cs b/extensions/Squidex.Extensions/Actions/Prerender/PrerenderPlugin.cs index 89e1a6c9b..fcf623e3f 100644 --- a/extensions/Squidex.Extensions/Actions/Prerender/PrerenderPlugin.cs +++ b/extensions/Squidex.Extensions/Actions/Prerender/PrerenderPlugin.cs @@ -7,7 +7,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Infrastructure.Plugins; namespace Squidex.Extensions.Actions.Prerender @@ -16,7 +15,7 @@ namespace Squidex.Extensions.Actions.Prerender { public void ConfigureServices(IServiceCollection services, IConfiguration configuration) { - RuleActionRegistry.Add(); + services.AddRuleAction(); } } } diff --git a/extensions/Squidex.Extensions/Actions/Slack/SlackAction.cs b/extensions/Squidex.Extensions/Actions/Slack/SlackAction.cs index 47e1dddc7..9b1382530 100644 --- a/extensions/Squidex.Extensions/Actions/Slack/SlackAction.cs +++ b/extensions/Squidex.Extensions/Actions/Slack/SlackAction.cs @@ -13,7 +13,6 @@ using Squidex.Infrastructure; namespace Squidex.Extensions.Actions.Slack { - [RuleActionHandler(typeof(SlackActionHandler))] [RuleAction( IconImage = "", IconColor = "#5c3a58", diff --git a/extensions/Squidex.Extensions/Actions/Slack/SlackPlugin.cs b/extensions/Squidex.Extensions/Actions/Slack/SlackPlugin.cs index 1149a5875..f0463c87e 100644 --- a/extensions/Squidex.Extensions/Actions/Slack/SlackPlugin.cs +++ b/extensions/Squidex.Extensions/Actions/Slack/SlackPlugin.cs @@ -7,7 +7,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Infrastructure.Plugins; namespace Squidex.Extensions.Actions.Slack @@ -16,7 +15,7 @@ namespace Squidex.Extensions.Actions.Slack { public void ConfigureServices(IServiceCollection services, IConfiguration configuration) { - RuleActionRegistry.Add(); + services.AddRuleAction(); } } } diff --git a/extensions/Squidex.Extensions/Actions/Twitter/TweetAction.cs b/extensions/Squidex.Extensions/Actions/Twitter/TweetAction.cs index c23b3dd98..5f68d9fd4 100644 --- a/extensions/Squidex.Extensions/Actions/Twitter/TweetAction.cs +++ b/extensions/Squidex.Extensions/Actions/Twitter/TweetAction.cs @@ -11,7 +11,6 @@ using Squidex.Domain.Apps.Core.Rules; namespace Squidex.Extensions.Actions.Twitter { - [RuleActionHandler(typeof(TweetActionHandler))] [RuleAction( IconImage = "", IconColor = "#1da1f2", diff --git a/extensions/Squidex.Extensions/Actions/Twitter/TwitterPlugin.cs b/extensions/Squidex.Extensions/Actions/Twitter/TwitterPlugin.cs index 911db17d3..fd59ec980 100644 --- a/extensions/Squidex.Extensions/Actions/Twitter/TwitterPlugin.cs +++ b/extensions/Squidex.Extensions/Actions/Twitter/TwitterPlugin.cs @@ -7,7 +7,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Infrastructure.Plugins; namespace Squidex.Extensions.Actions.Twitter @@ -19,7 +18,7 @@ namespace Squidex.Extensions.Actions.Twitter services.Configure( configuration.GetSection("twitter")); - RuleActionRegistry.Add(); + services.AddRuleAction(); } } } diff --git a/extensions/Squidex.Extensions/Actions/Webhook/WebhookAction.cs b/extensions/Squidex.Extensions/Actions/Webhook/WebhookAction.cs index cdd50c429..2cf8e339a 100644 --- a/extensions/Squidex.Extensions/Actions/Webhook/WebhookAction.cs +++ b/extensions/Squidex.Extensions/Actions/Webhook/WebhookAction.cs @@ -13,7 +13,6 @@ using Squidex.Infrastructure; namespace Squidex.Extensions.Actions.Webhook { - [RuleActionHandler(typeof(WebhookActionHandler))] [RuleAction( IconImage = "", IconColor = "#4bb958", diff --git a/extensions/Squidex.Extensions/Actions/Webhook/WebhookPlugin.cs b/extensions/Squidex.Extensions/Actions/Webhook/WebhookPlugin.cs index c9786cdf0..d729f1b5e 100644 --- a/extensions/Squidex.Extensions/Actions/Webhook/WebhookPlugin.cs +++ b/extensions/Squidex.Extensions/Actions/Webhook/WebhookPlugin.cs @@ -7,7 +7,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Infrastructure.Plugins; namespace Squidex.Extensions.Actions.Webhook @@ -16,7 +15,7 @@ namespace Squidex.Extensions.Actions.Webhook { public void ConfigureServices(IServiceCollection services, IConfiguration configuration) { - RuleActionRegistry.Add(); + services.AddRuleAction(); } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldRegistry.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldRegistry.cs index f4049da06..6154cff13 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldRegistry.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldRegistry.cs @@ -12,12 +12,12 @@ using Squidex.Infrastructure; namespace Squidex.Domain.Apps.Core.Schemas { - public static class FieldRegistry + public class FieldRegistry : ITypeProvider { private const string Suffix = "Properties"; private const string SuffixOld = "FieldProperties"; - public static TypeNameRegistry MapFields(this TypeNameRegistry typeNameRegistry) + public void Map(TypeNameRegistry typeNameRegistry) { var types = typeof(FieldRegistry).Assembly.GetTypes().Where(x => typeof(FieldProperties).IsAssignableFrom(x) && !x.IsAbstract); @@ -32,8 +32,6 @@ namespace Squidex.Domain.Apps.Core.Schemas typeNameRegistry.MapObsolete(type, type.TypeName(false, SuffixOld)); } } - - return typeNameRegistry; } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/SquidexCoreModel.cs b/src/Squidex.Domain.Apps.Core.Model/SquidexCoreModel.cs index 6f4f99495..860a9421a 100644 --- a/src/Squidex.Domain.Apps.Core.Model/SquidexCoreModel.cs +++ b/src/Squidex.Domain.Apps.Core.Model/SquidexCoreModel.cs @@ -9,7 +9,7 @@ using System.Reflection; namespace Squidex.Domain.Apps.Core { - public static class SquidexCoreModel + public sealed class SquidexCoreModel { public static readonly Assembly Assembly = typeof(SquidexCoreModel).Assembly; } diff --git a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/DependencyInjectionExtensions.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/DependencyInjectionExtensions.cs new file mode 100644 index 000000000..1113bcfbb --- /dev/null +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/DependencyInjectionExtensions.cs @@ -0,0 +1,25 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using Squidex.Domain.Apps.Core.HandleRules; +using Squidex.Domain.Apps.Core.Rules; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static class DependencyInjectionExtensions + { + public static IServiceCollection AddRuleAction(this IServiceCollection services) where THandler : class, IRuleActionHandler where TAction : RuleAction + { + services.AddSingletonAs() + .As(); + + services.AddSingleton(new RuleActionRegistration(typeof(TAction))); + + return services; + } + } +} diff --git a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionHandlerAttribute.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionHandlerAttribute.cs deleted file mode 100644 index 24d29ccea..000000000 --- a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionHandlerAttribute.cs +++ /dev/null @@ -1,30 +0,0 @@ -// ========================================================================== -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex UG (haftungsbeschraenkt) -// All rights reserved. Licensed under the MIT license. -// ========================================================================== - -using System; -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Core.HandleRules -{ - [AttributeUsage(AttributeTargets.Class, Inherited = false)] - public sealed class RuleActionHandlerAttribute : Attribute - { - public Type HandlerType { get; } - - public RuleActionHandlerAttribute(Type handlerType) - { - Guard.NotNull(handlerType, nameof(handlerType)); - - HandlerType = handlerType; - - if (!typeof(IRuleActionHandler).IsAssignableFrom(handlerType)) - { - throw new ArgumentException($"Handler type must implement {typeof(IRuleActionHandler)}.", nameof(handlerType)); - } - } - } -} diff --git a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionRegistration.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionRegistration.cs new file mode 100644 index 000000000..2d0477228 --- /dev/null +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionRegistration.cs @@ -0,0 +1,24 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using Squidex.Infrastructure; + +namespace Squidex.Domain.Apps.Core.HandleRules +{ + public sealed class RuleActionRegistration + { + public Type ActionType { get; } + + internal RuleActionRegistration(Type actionType) + { + Guard.NotNull(actionType, nameof(actionType)); + + ActionType = actionType; + } + } +} diff --git a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionRegistry.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionRegistry.cs deleted file mode 100644 index c1eebfb1e..000000000 --- a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionRegistry.cs +++ /dev/null @@ -1,175 +0,0 @@ -// ========================================================================== -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex UG (haftungsbeschraenkt) -// All rights reserved. Licensed under the MIT license. -// ========================================================================== - -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Reflection; -using Squidex.Domain.Apps.Core.Rules; -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Core.HandleRules -{ - public static class RuleActionRegistry - { - private const string ActionSuffix = "Action"; - private const string ActionSuffixV2 = "ActionV2"; - private static readonly HashSet ActionHandlerTypes = new HashSet(); - private static readonly Dictionary ActionTypes = new Dictionary(); - - public static IReadOnlyDictionary Actions - { - get { return ActionTypes; } - } - - public static IReadOnlyCollection ActionHandlers - { - get { return ActionHandlerTypes; } - } - - static RuleActionRegistry() - { - var actionTypes = - typeof(RuleActionRegistry).Assembly - .GetTypes() - .Where(x => typeof(RuleAction).IsAssignableFrom(x)) - .Where(x => x.GetCustomAttribute() != null) - .Where(x => x.GetCustomAttribute() != null) - .ToList(); - - foreach (var actionType in actionTypes) - { - Add(actionType); - } - } - - public static void Add() where T : RuleAction - { - Add(typeof(T)); - } - - private static void Add(Type actionType) - { - var metadata = actionType.GetCustomAttribute(); - - if (metadata == null) - { - return; - } - - var handlerAttribute = actionType.GetCustomAttribute(); - - if (handlerAttribute == null) - { - return; - } - - var name = GetActionName(actionType); - - var definition = - new RuleActionDefinition - { - Type = actionType, - Display = metadata.Display, - Description = metadata.Description, - IconColor = metadata.IconColor, - IconImage = metadata.IconImage, - ReadMore = metadata.ReadMore - }; - - foreach (var property in actionType.GetProperties()) - { - if (property.CanRead && property.CanWrite) - { - var actionProperty = new RuleActionProperty { Name = property.Name.ToCamelCase(), Display = property.Name }; - - var display = property.GetCustomAttribute(); - - if (!string.IsNullOrWhiteSpace(display?.Name)) - { - actionProperty.Display = display.Name; - } - - if (!string.IsNullOrWhiteSpace(display?.Description)) - { - actionProperty.Description = display.Description; - } - - var type = property.PropertyType; - - if ((property.GetCustomAttribute() != null || (type.IsValueType && !IsNullable(type))) && type != typeof(bool) && type != typeof(bool?)) - { - actionProperty.IsRequired = true; - } - - if (property.GetCustomAttribute() != null) - { - actionProperty.IsFormattable = true; - } - - var dataType = property.GetCustomAttribute()?.DataType; - - if (type == typeof(bool) || type == typeof(bool?)) - { - actionProperty.Editor = RuleActionPropertyEditor.Checkbox; - } - else if (type == typeof(int) || type == typeof(int?)) - { - actionProperty.Editor = RuleActionPropertyEditor.Number; - } - else if (dataType == DataType.Url) - { - actionProperty.Editor = RuleActionPropertyEditor.Url; - } - else if (dataType == DataType.Password) - { - actionProperty.Editor = RuleActionPropertyEditor.Password; - } - else if (dataType == DataType.EmailAddress) - { - actionProperty.Editor = RuleActionPropertyEditor.Email; - } - else if (dataType == DataType.MultilineText) - { - actionProperty.Editor = RuleActionPropertyEditor.TextArea; - } - else - { - actionProperty.Editor = RuleActionPropertyEditor.Text; - } - - definition.Properties.Add(actionProperty); - } - } - - ActionTypes[name] = definition; - - ActionHandlerTypes.Add(actionType.GetCustomAttribute().HandlerType); - } - - private static bool IsNullable(Type type) - { - return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>); - } - - public static TypeNameRegistry MapRuleActions(this TypeNameRegistry typeNameRegistry) - { - foreach (var actionType in ActionTypes.Values) - { - typeNameRegistry.Map(actionType.Type, actionType.Type.Name); - } - - return typeNameRegistry; - } - - private static string GetActionName(Type type) - { - return type.TypeName(false, ActionSuffix, ActionSuffixV2); - } - } -} diff --git a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleRegistry.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleRegistry.cs index 31228cadd..ac9789a9f 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleRegistry.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleRegistry.cs @@ -7,17 +7,151 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Linq; +using System.Reflection; using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents; using Squidex.Domain.Apps.Core.Rules; using Squidex.Infrastructure; +#pragma warning disable RECS0033 // Convert 'if' to '||' expression + namespace Squidex.Domain.Apps.Core.HandleRules { - public static class RuleRegistry + public sealed class RuleRegistry : ITypeProvider { - public static TypeNameRegistry MapRules(this TypeNameRegistry typeNameRegistry) + private const string ActionSuffix = "Action"; + private const string ActionSuffixV2 = "ActionV2"; + private readonly Dictionary actionTypes = new Dictionary(); + + public IReadOnlyDictionary Actions { + get { return actionTypes; } + } + + public RuleRegistry(IEnumerable registrations = null) + { + if (registrations != null) + { + foreach (var registration in registrations) + { + Add(registration.ActionType); + } + } + } + + public void Add() where T : RuleAction + { + Add(typeof(T)); + } + + private void Add(Type actionType) + { + var metadata = actionType.GetCustomAttribute(); + + if (metadata == null) + { + return; + } + + var name = GetActionName(actionType); + + var definition = + new RuleActionDefinition + { + Type = actionType, + Display = metadata.Display, + Description = metadata.Description, + IconColor = metadata.IconColor, + IconImage = metadata.IconImage, + ReadMore = metadata.ReadMore + }; + + foreach (var property in actionType.GetProperties()) + { + if (property.CanRead && property.CanWrite) + { + var actionProperty = new RuleActionProperty { Name = property.Name.ToCamelCase(), Display = property.Name }; + + var display = property.GetCustomAttribute(); + + if (!string.IsNullOrWhiteSpace(display?.Name)) + { + actionProperty.Display = display.Name; + } + + if (!string.IsNullOrWhiteSpace(display?.Description)) + { + actionProperty.Description = display.Description; + } + + var type = property.PropertyType; + + if ((property.GetCustomAttribute() != null || (type.IsValueType && !IsNullable(type))) && type != typeof(bool) && type != typeof(bool?)) + { + actionProperty.IsRequired = true; + } + + if (property.GetCustomAttribute() != null) + { + actionProperty.IsFormattable = true; + } + + var dataType = property.GetCustomAttribute()?.DataType; + + if (type == typeof(bool) || type == typeof(bool?)) + { + actionProperty.Editor = RuleActionPropertyEditor.Checkbox; + } + else if (type == typeof(int) || type == typeof(int?)) + { + actionProperty.Editor = RuleActionPropertyEditor.Number; + } + else if (dataType == DataType.Url) + { + actionProperty.Editor = RuleActionPropertyEditor.Url; + } + else if (dataType == DataType.Password) + { + actionProperty.Editor = RuleActionPropertyEditor.Password; + } + else if (dataType == DataType.EmailAddress) + { + actionProperty.Editor = RuleActionPropertyEditor.Email; + } + else if (dataType == DataType.MultilineText) + { + actionProperty.Editor = RuleActionPropertyEditor.TextArea; + } + else + { + actionProperty.Editor = RuleActionPropertyEditor.Text; + } + + definition.Properties.Add(actionProperty); + } + } + + actionTypes[name] = definition; + } + + private static bool IsNullable(Type type) + { + return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>); + } + + private static string GetActionName(Type type) + { + return type.TypeName(false, ActionSuffix, ActionSuffixV2); + } + + public void Map(TypeNameRegistry typeNameRegistry) + { + foreach (var actionType in actionTypes.Values) + { + typeNameRegistry.Map(actionType.Type, actionType.Type.Name); + } + var eventTypes = typeof(EnrichedEvent).Assembly.GetTypes().Where(x => typeof(EnrichedEvent).IsAssignableFrom(x) && !x.IsAbstract); var addedTypes = new HashSet(); @@ -39,8 +173,6 @@ namespace Squidex.Domain.Apps.Core.HandleRules typeNameRegistry.Map(type, type.Name); } } - - return typeNameRegistry; } } } diff --git a/src/Squidex.Domain.Apps.Events/SquidexEvents.cs b/src/Squidex.Domain.Apps.Events/SquidexEvents.cs index d49cb8921..7f85deb57 100644 --- a/src/Squidex.Domain.Apps.Events/SquidexEvents.cs +++ b/src/Squidex.Domain.Apps.Events/SquidexEvents.cs @@ -9,7 +9,7 @@ using System.Reflection; namespace Squidex.Domain.Apps.Events { - public static class SquidexEvents + public sealed class SquidexEvents { public static readonly Assembly Assembly = typeof(SquidexEvents).Assembly; } diff --git a/src/Squidex.Infrastructure.MongoDb/States/MongoSnapshotStore.cs b/src/Squidex.Infrastructure.MongoDb/States/MongoSnapshotStore.cs index 3f0a356b1..2b6cd2643 100644 --- a/src/Squidex.Infrastructure.MongoDb/States/MongoSnapshotStore.cs +++ b/src/Squidex.Infrastructure.MongoDb/States/MongoSnapshotStore.cs @@ -5,10 +5,12 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System; using System.Linq; using System.Threading.Tasks; using MongoDB.Bson; using MongoDB.Driver; +using Newtonsoft.Json; using Squidex.Infrastructure.Log; using Squidex.Infrastructure.MongoDb; @@ -16,9 +18,12 @@ namespace Squidex.Infrastructure.States { public class MongoSnapshotStore : MongoRepositoryBase>, ISnapshotStore { - public MongoSnapshotStore(IMongoDatabase database) + public MongoSnapshotStore(IMongoDatabase database, JsonSerializer jsonSerializer) : base(database) { + Guard.NotNull(jsonSerializer, nameof(jsonSerializer)); + + BsonJsonConvention.Register(jsonSerializer); } protected override string CollectionName() @@ -55,7 +60,7 @@ namespace Squidex.Infrastructure.States } } - public async Task ReadAllAsync(System.Func callback) + public async Task ReadAllAsync(Func callback) { using (Profiler.TraceMethod>()) { diff --git a/src/Squidex.Infrastructure/AutoAssembyTypeProvider.cs b/src/Squidex.Infrastructure/AutoAssembyTypeProvider.cs new file mode 100644 index 000000000..1cb4f5ee5 --- /dev/null +++ b/src/Squidex.Infrastructure/AutoAssembyTypeProvider.cs @@ -0,0 +1,17 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +namespace Squidex.Infrastructure +{ + public sealed class AutoAssembyTypeProvider : ITypeProvider + { + public void Map(TypeNameRegistry typeNameRegistry) + { + typeNameRegistry.MapUnmapped(typeof(T).Assembly); + } + } +} diff --git a/src/Squidex.Infrastructure/Configuration/ConfigurationExtensions.cs b/src/Squidex.Infrastructure/Configuration/ConfigurationExtensions.cs index 2194f753b..62d0521a4 100644 --- a/src/Squidex.Infrastructure/Configuration/ConfigurationExtensions.cs +++ b/src/Squidex.Infrastructure/Configuration/ConfigurationExtensions.cs @@ -7,9 +7,9 @@ using System.Globalization; using System.Linq; -using Microsoft.Extensions.Configuration; +using Squidex.Infrastructure; -namespace Squidex.Infrastructure.Configuration +namespace Microsoft.Extensions.Configuration { public static class ConfigurationExtensions { diff --git a/src/Squidex.Infrastructure/Configuration/Options.cs b/src/Squidex.Infrastructure/Configuration/Options.cs index 79a3cdfae..89cb9f596 100644 --- a/src/Squidex.Infrastructure/Configuration/Options.cs +++ b/src/Squidex.Infrastructure/Configuration/Options.cs @@ -8,7 +8,7 @@ using System; using System.Collections.Generic; -namespace Squidex.Infrastructure.Configuration +namespace Microsoft.Extensions.Configuration { public sealed class Options : Dictionary { diff --git a/src/Squidex.Infrastructure/DependencyInjection/DependencyInjectionExtensions.cs b/src/Squidex.Infrastructure/DependencyInjection/DependencyInjectionExtensions.cs index 5b39ad14b..da40d75eb 100644 --- a/src/Squidex.Infrastructure/DependencyInjection/DependencyInjectionExtensions.cs +++ b/src/Squidex.Infrastructure/DependencyInjection/DependencyInjectionExtensions.cs @@ -7,10 +7,10 @@ using System; using System.Linq; -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; +using Squidex.Infrastructure; -namespace Squidex.Infrastructure.DependencyInjection +namespace Microsoft.Extensions.DependencyInjection { public static class DependencyInjectionExtensions { diff --git a/src/Squidex.Infrastructure/ITypeProvider.cs b/src/Squidex.Infrastructure/ITypeProvider.cs new file mode 100644 index 000000000..63ee58238 --- /dev/null +++ b/src/Squidex.Infrastructure/ITypeProvider.cs @@ -0,0 +1,14 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +namespace Squidex.Infrastructure +{ + public interface ITypeProvider + { + void Map(TypeNameRegistry typeNameRegistry); + } +} diff --git a/src/Squidex.Infrastructure/Log/ApplicationInfoLogAppender.cs b/src/Squidex.Infrastructure/Log/ApplicationInfoLogAppender.cs index 9763aabf8..9d13c43b8 100644 --- a/src/Squidex.Infrastructure/Log/ApplicationInfoLogAppender.cs +++ b/src/Squidex.Infrastructure/Log/ApplicationInfoLogAppender.cs @@ -17,7 +17,7 @@ namespace Squidex.Infrastructure.Log private readonly string applicationSessionId; public ApplicationInfoLogAppender(Type type, Guid applicationSession) - : this(type?.GetTypeInfo().Assembly, applicationSession) + : this(type?.Assembly, applicationSession) { } diff --git a/src/Squidex.Infrastructure/Reflection/ReflectionExtensions.cs b/src/Squidex.Infrastructure/Reflection/ReflectionExtensions.cs index 474f55355..55354eb13 100644 --- a/src/Squidex.Infrastructure/Reflection/ReflectionExtensions.cs +++ b/src/Squidex.Infrastructure/Reflection/ReflectionExtensions.cs @@ -21,7 +21,7 @@ namespace Squidex.Infrastructure.Reflection BindingFlags.Public | BindingFlags.Instance; - if (!type.GetTypeInfo().IsInterface) + if (!type.IsInterface) { return type.GetProperties(bindingFlags); } diff --git a/src/Squidex.Infrastructure/SquidexInfrastructure.cs b/src/Squidex.Infrastructure/SquidexInfrastructure.cs index 8dac58f91..20444d138 100644 --- a/src/Squidex.Infrastructure/SquidexInfrastructure.cs +++ b/src/Squidex.Infrastructure/SquidexInfrastructure.cs @@ -9,7 +9,7 @@ using System.Reflection; namespace Squidex.Infrastructure { - public static class SquidexInfrastructure + public sealed class SquidexInfrastructure { public static readonly Assembly Assembly = typeof(SquidexInfrastructure).Assembly; } diff --git a/src/Squidex.Infrastructure/TypeNameRegistry.cs b/src/Squidex.Infrastructure/TypeNameRegistry.cs index 233f5ee28..5df5f9f00 100644 --- a/src/Squidex.Infrastructure/TypeNameRegistry.cs +++ b/src/Squidex.Infrastructure/TypeNameRegistry.cs @@ -16,6 +16,17 @@ namespace Squidex.Infrastructure private readonly Dictionary namesByType = new Dictionary(); private readonly Dictionary typesByName = new Dictionary(StringComparer.OrdinalIgnoreCase); + public TypeNameRegistry(IEnumerable providers = null) + { + if (providers != null) + { + foreach (var provider in providers) + { + Map(provider); + } + } + } + public TypeNameRegistry MapObsolete(Type type, string name) { Guard.NotNull(type, nameof(type)); @@ -36,11 +47,20 @@ namespace Squidex.Infrastructure return this; } + public TypeNameRegistry Map(ITypeProvider provider) + { + Guard.NotNull(provider, nameof(provider)); + + provider.Map(this); + + return this; + } + public TypeNameRegistry Map(Type type) { Guard.NotNull(type, nameof(type)); - var typeNameAttribute = type.GetTypeInfo().GetCustomAttribute(); + var typeNameAttribute = type.GetCustomAttribute(); if (!string.IsNullOrWhiteSpace(typeNameAttribute?.TypeName)) { diff --git a/src/Squidex/Areas/Api/Config/Swagger/SwaggerServices.cs b/src/Squidex/Areas/Api/Config/Swagger/SwaggerServices.cs index 07a973ea4..ddccd616c 100644 --- a/src/Squidex/Areas/Api/Config/Swagger/SwaggerServices.cs +++ b/src/Squidex/Areas/Api/Config/Swagger/SwaggerServices.cs @@ -15,7 +15,6 @@ using NSwag.SwaggerGeneration.Processors; using Squidex.Areas.Api.Controllers.Contents.Generator; using Squidex.Areas.Api.Controllers.Rules.Models; using Squidex.Infrastructure; -using Squidex.Infrastructure.DependencyInjection; namespace Squidex.Areas.Api.Config.Swagger { diff --git a/src/Squidex/Areas/Api/Config/Swagger/XmlTagProcessor.cs b/src/Squidex/Areas/Api/Config/Swagger/XmlTagProcessor.cs index 01dc1c73b..b0ecdf36d 100644 --- a/src/Squidex/Areas/Api/Config/Swagger/XmlTagProcessor.cs +++ b/src/Squidex/Areas/Api/Config/Swagger/XmlTagProcessor.cs @@ -22,7 +22,7 @@ namespace Squidex.Areas.Api.Config.Swagger { foreach (var controllerType in context.ControllerTypes) { - var attribute = controllerType.GetTypeInfo().GetCustomAttribute(); + var attribute = controllerType.GetCustomAttribute(); if (attribute != null) { diff --git a/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleActionConverter.cs b/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleActionConverter.cs index b36243b4f..50b4446e0 100644 --- a/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleActionConverter.cs +++ b/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleActionConverter.cs @@ -7,15 +7,13 @@ using System; using System.Collections.Generic; -using System.Linq; -using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.Rules; namespace Squidex.Areas.Api.Controllers.Rules.Models { public sealed class RuleActionConverter : MyJsonInheritanceConverter { - private static readonly Dictionary Mapping = RuleActionRegistry.Actions.ToDictionary(x => x.Key, x => x.Value.Type); + public static IReadOnlyDictionary Mapping { get; set; } public RuleActionConverter() : base("actionType", Mapping) diff --git a/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleActionProcessor.cs b/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleActionProcessor.cs index b2abd5b91..b0337ed42 100644 --- a/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleActionProcessor.cs +++ b/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleActionProcessor.cs @@ -13,11 +13,21 @@ using NSwag.SwaggerGeneration.Processors; using NSwag.SwaggerGeneration.Processors.Contexts; using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.Rules; +using Squidex.Infrastructure; namespace Squidex.Areas.Api.Controllers.Rules.Models { public sealed class RuleActionProcessor : IDocumentProcessor { + private readonly RuleRegistry ruleRegistry; + + public RuleActionProcessor(RuleRegistry ruleRegistry) + { + Guard.NotNull(ruleRegistry, nameof(ruleRegistry)); + + this.ruleRegistry = ruleRegistry; + } + public async Task ProcessAsync(DocumentProcessorContext context) { try @@ -36,16 +46,16 @@ namespace Squidex.Areas.Api.Controllers.Rules.Models Type = JsonObjectType.String, IsRequired = true }; - foreach (var derived in RuleActionRegistry.Actions) + foreach (var action in ruleRegistry.Actions) { - var derivedSchema = await context.SchemaGenerator.GenerateAsync(derived.Value.Type, context.SchemaResolver); + var derivedSchema = await context.SchemaGenerator.GenerateAsync(action.Value.Type, context.SchemaResolver); var oldName = context.Document.Definitions.FirstOrDefault(x => x.Value == derivedSchema).Key; if (oldName != null) { context.Document.Definitions.Remove(oldName); - context.Document.Definitions.Add(derived.Key, derivedSchema); + context.Document.Definitions.Add(action.Key, derivedSchema); } } diff --git a/src/Squidex/Areas/Api/Controllers/Rules/RulesController.cs b/src/Squidex/Areas/Api/Controllers/Rules/RulesController.cs index d3d7edd1b..edecc7b6f 100644 --- a/src/Squidex/Areas/Api/Controllers/Rules/RulesController.cs +++ b/src/Squidex/Areas/Api/Controllers/Rules/RulesController.cs @@ -30,17 +30,18 @@ namespace Squidex.Areas.Api.Controllers.Rules [ApiExplorerSettings(GroupName = nameof(Rules))] public sealed class RulesController : ApiController { - private static readonly string RuleActionsEtag = string.Join(";", RuleActionRegistry.Actions.Select(x => x.Key)).Sha256Base64(); private readonly IAppProvider appProvider; private readonly IRuleEventRepository ruleEventsRepository; + private readonly RuleRegistry ruleRegistry; public RulesController(ICommandBus commandBus, IAppProvider appProvider, - IRuleEventRepository ruleEventsRepository) + IRuleEventRepository ruleEventsRepository, RuleRegistry ruleRegistry) : base(commandBus) { this.appProvider = appProvider; this.ruleEventsRepository = ruleEventsRepository; + this.ruleRegistry = ruleRegistry; } /// @@ -56,9 +57,11 @@ namespace Squidex.Areas.Api.Controllers.Rules [ApiCosts(0)] public IActionResult GetActions() { - var response = RuleActionRegistry.Actions.ToDictionary(x => x.Key, x => RuleElementDto.FromDefinition(x.Value)); + var etag = string.Join(";", ruleRegistry.Actions.Select(x => x.Key)).Sha256Base64(); - Response.Headers[HeaderNames.ETag] = RuleActionsEtag; + var response = ruleRegistry.Actions.ToDictionary(x => x.Key, x => RuleElementDto.FromDefinition(x.Value)); + + Response.Headers[HeaderNames.ETag] = etag; return Ok(response); } diff --git a/src/Squidex/Areas/Api/Controllers/Users/UsersController.cs b/src/Squidex/Areas/Api/Controllers/Users/UsersController.cs index 3aef01d84..ea9cc4de7 100644 --- a/src/Squidex/Areas/Api/Controllers/Users/UsersController.cs +++ b/src/Squidex/Areas/Api/Controllers/Users/UsersController.cs @@ -9,7 +9,6 @@ using System; using System.IO; using System.Linq; using System.Net.Http; -using System.Reflection; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Squidex.Areas.Api.Controllers.Users.Models; @@ -34,7 +33,7 @@ namespace Squidex.Areas.Api.Controllers.Users static UsersController() { - var assembly = typeof(UsersController).GetTypeInfo().Assembly; + var assembly = typeof(UsersController).Assembly; using (var avatarStream = assembly.GetManifestResourceStream("Squidex.Areas.Api.Controllers.Users.Assets.Avatar.png")) { diff --git a/src/Squidex/Areas/IdentityServer/Config/IdentityServerServices.cs b/src/Squidex/Areas/IdentityServer/Config/IdentityServerServices.cs index f5025efd6..ef07a13b6 100644 --- a/src/Squidex/Areas/IdentityServer/Config/IdentityServerServices.cs +++ b/src/Squidex/Areas/IdentityServer/Config/IdentityServerServices.cs @@ -6,7 +6,6 @@ // ========================================================================== using System.Collections.Generic; -using System.Reflection; using System.Security.Cryptography.X509Certificates; using IdentityModel; using IdentityServer4.Models; @@ -29,7 +28,7 @@ namespace Squidex.Areas.IdentityServer.Config { X509Certificate2 certificate; - var assembly = typeof(IdentityServerServices).GetTypeInfo().Assembly; + var assembly = typeof(IdentityServerServices).Assembly; using (var certStream = assembly.GetManifestResourceStream("Squidex.Areas.IdentityServer.Config.Cert.IdentityCert.pfx")) { diff --git a/src/Squidex/Config/Domain/AssetServices.cs b/src/Squidex/Config/Domain/AssetServices.cs index d23731ed3..617c8ff8c 100644 --- a/src/Squidex/Config/Domain/AssetServices.cs +++ b/src/Squidex/Config/Domain/AssetServices.cs @@ -12,8 +12,6 @@ using MongoDB.Driver.GridFS; using Squidex.Infrastructure; using Squidex.Infrastructure.Assets; using Squidex.Infrastructure.Assets.ImageSharp; -using Squidex.Infrastructure.Configuration; -using Squidex.Infrastructure.DependencyInjection; using Squidex.Infrastructure.Log; namespace Squidex.Config.Domain diff --git a/src/Squidex/Config/Domain/EntitiesServices.cs b/src/Squidex/Config/Domain/EntitiesServices.cs index 3bf99f5a2..c7a215257 100644 --- a/src/Squidex/Config/Domain/EntitiesServices.cs +++ b/src/Squidex/Config/Domain/EntitiesServices.cs @@ -42,8 +42,6 @@ using Squidex.Domain.Apps.Entities.Schemas.Indexes; using Squidex.Domain.Apps.Entities.Tags; using Squidex.Infrastructure.Assets; using Squidex.Infrastructure.Commands; -using Squidex.Infrastructure.Configuration; -using Squidex.Infrastructure.DependencyInjection; using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.Migrations; using Squidex.Pipeline; diff --git a/src/Squidex/Config/Domain/EventPublishersServices.cs b/src/Squidex/Config/Domain/EventPublishersServices.cs index 82004c1db..dad6cd6ec 100644 --- a/src/Squidex/Config/Domain/EventPublishersServices.cs +++ b/src/Squidex/Config/Domain/EventPublishersServices.cs @@ -10,7 +10,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Squidex.Infrastructure; using Squidex.Infrastructure.CQRS.Events; -using Squidex.Infrastructure.DependencyInjection; using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.Json; diff --git a/src/Squidex/Config/Domain/EventStoreServices.cs b/src/Squidex/Config/Domain/EventStoreServices.cs index 94bebf145..abd77f817 100644 --- a/src/Squidex/Config/Domain/EventStoreServices.cs +++ b/src/Squidex/Config/Domain/EventStoreServices.cs @@ -11,8 +11,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using MongoDB.Driver; using Squidex.Infrastructure; -using Squidex.Infrastructure.Configuration; -using Squidex.Infrastructure.DependencyInjection; using Squidex.Infrastructure.Diagnostics; using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.EventSourcing.Grains; @@ -47,12 +45,14 @@ namespace Squidex.Config.Domain var eventStoreProjectionHost = config.GetRequiredValue("eventStore:getEventStore:projectionHost"); var eventStorePrefix = config.GetValue("eventStore:getEventStore:prefix"); - var connection = EventStoreConnection.Create(eventStoreConfiguration); - - services.AddSingletonAs(connection) + services.AddSingletonAs(_ => EventStoreConnection.Create(eventStoreConfiguration)) .As(); - services.AddSingletonAs(c => new GetEventStore(connection, c.GetRequiredService(), eventStorePrefix, eventStoreProjectionHost)) + services.AddSingletonAs(c => new GetEventStore( + c.GetRequiredService(), + c.GetRequiredService(), + eventStorePrefix, + eventStoreProjectionHost)) .AsOptional(); services.AddHealthChecks() diff --git a/src/Squidex/Config/Domain/InfrastructureServices.cs b/src/Squidex/Config/Domain/InfrastructureServices.cs index 9ae8bf331..8e1b2e042 100644 --- a/src/Squidex/Config/Domain/InfrastructureServices.cs +++ b/src/Squidex/Config/Domain/InfrastructureServices.cs @@ -18,7 +18,6 @@ using Squidex.Domain.Apps.Entities.Apps.Diagnostics; using Squidex.Domain.Users; using Squidex.Infrastructure; using Squidex.Infrastructure.Caching; -using Squidex.Infrastructure.DependencyInjection; using Squidex.Infrastructure.Diagnostics; using Squidex.Infrastructure.Translations; using Squidex.Infrastructure.UsageTracking; diff --git a/src/Squidex/Config/Domain/LoggingServices.cs b/src/Squidex/Config/Domain/LoggingServices.cs index dfc45d04c..59e7932e3 100644 --- a/src/Squidex/Config/Domain/LoggingServices.cs +++ b/src/Squidex/Config/Domain/LoggingServices.cs @@ -9,7 +9,6 @@ using System; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Squidex.Domain.Apps.Entities.Apps; -using Squidex.Infrastructure.DependencyInjection; using Squidex.Infrastructure.Log; using Squidex.Pipeline; diff --git a/src/Squidex/Config/Domain/RuleServices.cs b/src/Squidex/Config/Domain/RuleServices.cs index 685bc2077..eb8ad2cca 100644 --- a/src/Squidex/Config/Domain/RuleServices.cs +++ b/src/Squidex/Config/Domain/RuleServices.cs @@ -12,7 +12,7 @@ using Squidex.Domain.Apps.Entities.Contents; using Squidex.Domain.Apps.Entities.Rules; using Squidex.Domain.Apps.Entities.Rules.UsageTracking; using Squidex.Domain.Apps.Entities.Schemas; -using Squidex.Infrastructure.DependencyInjection; +using Squidex.Infrastructure; using Squidex.Infrastructure.EventSourcing; namespace Squidex.Config.Domain @@ -39,16 +39,14 @@ namespace Squidex.Config.Domain services.AddSingletonAs() .As(); + services.AddSingletonAs() + .As().AsSelf(); + services.AddSingletonAs() .AsSelf(); services.AddSingletonAs() .AsSelf(); - - foreach (var actionHandler in RuleActionRegistry.ActionHandlers) - { - services.AddSingleton(typeof(IRuleActionHandler), actionHandler); - } } } } diff --git a/src/Squidex/Config/Domain/SerializationInitializer.cs b/src/Squidex/Config/Domain/SerializationInitializer.cs new file mode 100644 index 000000000..bdec8c549 --- /dev/null +++ b/src/Squidex/Config/Domain/SerializationInitializer.cs @@ -0,0 +1,41 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Newtonsoft.Json; +using Squidex.Areas.Api.Controllers.Rules.Models; +using Squidex.Domain.Apps.Core.HandleRules; +using Squidex.Infrastructure; +using Squidex.Infrastructure.MongoDb; +using Squidex.Infrastructure.Tasks; + +namespace Squidex.Config.Domain +{ + public sealed class SerializationInitializer : IInitializable + { + private readonly JsonSerializer jsonSerializer; + private readonly RuleRegistry ruleRegistry; + + public SerializationInitializer(JsonSerializer jsonSerializer, RuleRegistry ruleRegistry) + { + this.jsonSerializer = jsonSerializer; + + this.ruleRegistry = ruleRegistry; + } + + public Task InitializeAsync(CancellationToken ct = default) + { + BsonJsonConvention.Register(jsonSerializer); + + RuleActionConverter.Mapping = ruleRegistry.Actions.ToDictionary(x => x.Key, x => x.Value.Type); + + return TaskHelper.Done; + } + } +} diff --git a/src/Squidex/Config/Domain/SerializationServices.cs b/src/Squidex/Config/Domain/SerializationServices.cs index 4ef371ba4..30f1b27bf 100644 --- a/src/Squidex/Config/Domain/SerializationServices.cs +++ b/src/Squidex/Config/Domain/SerializationServices.cs @@ -11,7 +11,6 @@ using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Squidex.Domain.Apps.Core; using Squidex.Domain.Apps.Core.Apps.Json; -using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.Rules.Json; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.Schemas.Json; @@ -24,23 +23,8 @@ namespace Squidex.Config.Domain { public static class SerializationServices { - private static readonly TypeNameRegistry TypeNameRegistry = - new TypeNameRegistry() - .MapFields() - .MapRules() - .MapRuleActions() - .MapUnmapped(SquidexCoreModel.Assembly) - .MapUnmapped(SquidexEvents.Assembly) - .MapUnmapped(SquidexInfrastructure.Assembly) - .MapUnmapped(SquidexMigrations.Assembly); - - public static readonly JsonSerializerSettings DefaultJsonSettings = new JsonSerializerSettings(); - public static readonly JsonSerializer DefaultJsonSerializer; - - private static void ConfigureJson(JsonSerializerSettings settings, TypeNameHandling typeNameHandling) + private static JsonSerializerSettings ConfigureJson(JsonSerializerSettings settings, TypeNameHandling typeNameHandling) { - settings.SerializationBinder = new TypeNameSerializationBinder(TypeNameRegistry); - settings.ContractResolver = new ConverterContractResolver( new AppClientsConverter(), new AppContributorsConverter(), @@ -66,22 +50,52 @@ namespace Squidex.Config.Domain settings.DateParseHandling = DateParseHandling.None; settings.TypeNameHandling = typeNameHandling; - } - - static SerializationServices() - { - ConfigureJson(DefaultJsonSettings, TypeNameHandling.Auto); - DefaultJsonSerializer = JsonSerializer.Create(DefaultJsonSettings); + return settings; } public static IServiceCollection AddMySerializers(this IServiceCollection services) { - services.AddSingleton(DefaultJsonSettings); - services.AddSingleton(DefaultJsonSerializer); - services.AddSingleton(TypeNameRegistry); + services.AddSingletonAs>() + .As(); + + services.AddSingletonAs>() + .As(); + + services.AddSingletonAs>() + .As(); + + services.AddSingletonAs>() + .As(); + + services.AddSingletonAs() + .As(); + + services.AddSingletonAs() + .As(); + + services.AddSingletonAs() + .AsSelf(); + + services.AddSingletonAs() + .AsSelf(); + + services.AddSingletonAs(c => JsonSerializer.Create(c.GetRequiredService())) + .AsSelf(); + + services.AddSingletonAs(c => + { + var serializerSettings = ConfigureJson(new JsonSerializerSettings(), TypeNameHandling.Auto); + + var typeNameRegistry = c.GetService(); + + if (typeNameRegistry != null) + { + serializerSettings.SerializationBinder = new TypeNameSerializationBinder(typeNameRegistry); + } - services.AddSingleton(new NewtonsoftJsonSerializer(DefaultJsonSettings)); + return serializerSettings; + }).As(); return services; } diff --git a/src/Squidex/Config/Domain/StoreServices.cs b/src/Squidex/Config/Domain/StoreServices.cs index bf077d755..a980bafc6 100644 --- a/src/Squidex/Config/Domain/StoreServices.cs +++ b/src/Squidex/Config/Domain/StoreServices.cs @@ -27,13 +27,10 @@ using Squidex.Domain.Users; using Squidex.Domain.Users.MongoDb; using Squidex.Domain.Users.MongoDb.Infrastructure; using Squidex.Infrastructure; -using Squidex.Infrastructure.Configuration; -using Squidex.Infrastructure.DependencyInjection; using Squidex.Infrastructure.Diagnostics; using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.Json; using Squidex.Infrastructure.Migrations; -using Squidex.Infrastructure.MongoDb; using Squidex.Infrastructure.States; using Squidex.Infrastructure.UsageTracking; @@ -47,23 +44,20 @@ namespace Squidex.Config.Domain { ["MongoDB"] = () => { - BsonJsonConvention.Register(SerializationServices.DefaultJsonSerializer); - var mongoConfiguration = config.GetRequiredValue("store:mongoDb:configuration"); var mongoDatabaseName = config.GetRequiredValue("store:mongoDb:database"); var mongoContentDatabaseName = config.GetOptionalValue("store:mongoDb:contentDatabase", mongoDatabaseName); - var mongoClient = Singletons.GetOrAdd(mongoConfiguration, s => new MongoClient(s)); - var mongoDatabase = mongoClient.GetDatabase(mongoDatabaseName); - var mongoContentDatabase = mongoClient.GetDatabase(mongoContentDatabaseName); - services.AddSingleton(typeof(ISnapshotStore<,>), typeof(MongoSnapshotStore<,>)); - services.AddSingletonAs(mongoDatabase) + services.AddSingletonAs(c => Singletons.GetOrAdd(mongoConfiguration, s => new MongoClient(s))) + .As(); + + services.AddSingletonAs(c => c.GetRequiredService().GetDatabase(mongoDatabaseName)) .As(); - services.AddHealthChecks() - .AddCheck("MongoDB", tags: new[] { "node" }); + services.AddTransientAs(c => new DeleteContentCollections(c.GetRequiredService().GetDatabase(mongoContentDatabaseName))) + .As(); services.AddSingletonAs() .As(); @@ -74,8 +68,8 @@ namespace Squidex.Config.Domain services.AddTransientAs() .As(); - services.AddTransientAs(c => new DeleteContentCollections(mongoContentDatabase)) - .As(); + services.AddHealthChecks() + .AddCheck("MongoDB", tags: new[] { "node" }); services.AddSingletonAs() .AsOptional(); @@ -100,7 +94,10 @@ namespace Squidex.Config.Domain .AsOptional() .AsOptional>(); - services.AddSingletonAs(c => new MongoContentRepository(mongoContentDatabase, c.GetRequiredService(), c.GetRequiredService())) + services.AddSingletonAs(c => new MongoContentRepository( + c.GetRequiredService().GetDatabase(mongoContentDatabaseName), + c.GetRequiredService(), + c.GetRequiredService())) .AsOptional() .AsOptional>() .AsOptional(); diff --git a/src/Squidex/Config/Domain/SubscriptionServices.cs b/src/Squidex/Config/Domain/SubscriptionServices.cs index 2d2a0e706..f5f8ad07b 100644 --- a/src/Squidex/Config/Domain/SubscriptionServices.cs +++ b/src/Squidex/Config/Domain/SubscriptionServices.cs @@ -12,7 +12,6 @@ using Squidex.Domain.Apps.Entities.Apps.Services; using Squidex.Domain.Apps.Entities.Apps.Services.Implementations; using Squidex.Domain.Users; using Squidex.Infrastructure; -using Squidex.Infrastructure.DependencyInjection; namespace Squidex.Config.Domain { diff --git a/src/Squidex/Config/Orleans/OrleansServices.cs b/src/Squidex/Config/Orleans/OrleansServices.cs index 957a3cda5..aed630ded 100644 --- a/src/Squidex/Config/Orleans/OrleansServices.cs +++ b/src/Squidex/Config/Orleans/OrleansServices.cs @@ -15,7 +15,6 @@ using Orleans.Hosting; using Squidex.Domain.Apps.Entities.Contents; using Squidex.Domain.Apps.Entities.Rules; using Squidex.Domain.Apps.Entities.Rules.UsageTracking; -using Squidex.Infrastructure.Configuration; using Squidex.Infrastructure.EventSourcing.Grains; using Squidex.Infrastructure.Orleans; diff --git a/src/Squidex/Config/Web/WebServices.cs b/src/Squidex/Config/Web/WebServices.cs index 3bafa44be..b94410f97 100644 --- a/src/Squidex/Config/Web/WebServices.cs +++ b/src/Squidex/Config/Web/WebServices.cs @@ -9,7 +9,6 @@ using Microsoft.AspNetCore.Authentication; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Squidex.Config.Domain; -using Squidex.Infrastructure.DependencyInjection; using Squidex.Pipeline; using Squidex.Pipeline.Plugins; using Squidex.Pipeline.Robots; diff --git a/src/Squidex/Pipeline/Squid/SquidMiddleware.cs b/src/Squidex/Pipeline/Squid/SquidMiddleware.cs index 157c3c381..8bf5d0fb7 100644 --- a/src/Squidex/Pipeline/Squid/SquidMiddleware.cs +++ b/src/Squidex/Pipeline/Squid/SquidMiddleware.cs @@ -7,7 +7,6 @@ using System.Collections.Generic; using System.IO; -using System.Reflection; using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; @@ -128,7 +127,7 @@ namespace Squidex.Pipeline.Squid private static string LoadSvg(string name) { - var assembly = typeof(SquidMiddleware).GetTypeInfo().Assembly; + var assembly = typeof(SquidMiddleware).Assembly; using (var resourceStream = assembly.GetManifestResourceStream($"Squidex.Pipeline.Squid.icon-{name}.svg")) { diff --git a/src/Squidex/Pipeline/Swagger/NSwagHelper.cs b/src/Squidex/Pipeline/Swagger/NSwagHelper.cs index 6cdc3be8d..ccc236f1f 100644 --- a/src/Squidex/Pipeline/Swagger/NSwagHelper.cs +++ b/src/Squidex/Pipeline/Swagger/NSwagHelper.cs @@ -9,7 +9,6 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Reflection; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using NJsonSchema; @@ -23,7 +22,7 @@ namespace Squidex.Pipeline.Swagger { public static string LoadDocs(string name) { - var assembly = typeof(NSwagHelper).GetTypeInfo().Assembly; + var assembly = typeof(NSwagHelper).Assembly; using (var resourceStream = assembly.GetManifestResourceStream($"Squidex.Docs.{name}.md")) { diff --git a/src/Squidex/WebStartup.cs b/src/Squidex/WebStartup.cs index 0c29f400d..a23db7df9 100644 --- a/src/Squidex/WebStartup.cs +++ b/src/Squidex/WebStartup.cs @@ -26,7 +26,6 @@ using Squidex.Config.Startup; using Squidex.Config.Web; using Squidex.Domain.Apps.Entities.Assets; using Squidex.Domain.Apps.Entities.Contents; -using Squidex.Extensions.Actions.Twitter; using Squidex.Infrastructure.Commands; using Squidex.Infrastructure.Diagnostics; using Squidex.Infrastructure.Translations; diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleElementRegistry.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleElementRegistryTests.cs similarity index 93% rename from tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleElementRegistry.cs rename to tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleElementRegistryTests.cs index 3cef0cc4d..d7f647d61 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleElementRegistry.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleElementRegistryTests.cs @@ -15,8 +15,10 @@ using Xunit; namespace Squidex.Domain.Apps.Core.Operations.HandleRules { - public class RuleElementRegistry + public class RuleElementRegistryTests { + private readonly RuleRegistry sut = new RuleRegistry(); + private abstract class MyRuleActionHandler : RuleActionHandler { protected MyRuleActionHandler(RuleEventFormatter formatter) @@ -25,7 +27,6 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules } } - [RuleActionHandler(typeof(MyRuleActionHandler))] [RuleAction( IconImage = "", IconColor = "#1e5470", @@ -52,12 +53,16 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules [DataType(DataType.Password)] public string Password { get; set; } + [DataType(DataType.Custom)] public bool Boolean { get; set; } + [DataType(DataType.Custom)] public bool? BooleanOptional { get; set; } + [DataType(DataType.Custom)] public int Number { get; set; } + [DataType(DataType.Custom)] public int? NumberOptional { get; set; } } @@ -156,9 +161,9 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules IsRequired = false }); - RuleActionRegistry.Add(); + sut.Add(); - var currentDefinition = RuleActionRegistry.Actions.Values.First(); + var currentDefinition = sut.Actions.Values.First(); currentDefinition.Should().BeEquivalentTo(expected); } diff --git a/tests/Squidex.Domain.Apps.Core.Tests/TestUtils.cs b/tests/Squidex.Domain.Apps.Core.Tests/TestUtils.cs index 6723ddeb2..64ee059ea 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/TestUtils.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/TestUtils.cs @@ -31,8 +31,8 @@ namespace Squidex.Domain.Apps.Core { var typeNameRegistry = new TypeNameRegistry() - .MapFields() - .MapRules() + .Map(new FieldRegistry()) + .Map(new RuleRegistry()) .MapUnmapped(typeof(TestUtils).Assembly); var serializerSettings = new JsonSerializerSettings @@ -123,7 +123,7 @@ namespace Squidex.Domain.Apps.Core foreach (var property in sut.GetType().GetRuntimeProperties().Where(x => x.Name != "IsFrozen")) { var value = - property.PropertyType.GetTypeInfo().IsValueType ? + property.PropertyType.IsValueType ? Activator.CreateInstance(property.PropertyType) : null; @@ -139,7 +139,7 @@ namespace Squidex.Domain.Apps.Core foreach (var property in sut.GetType().GetRuntimeProperties().Where(x => x.Name != "IsFrozen")) { var value = - property.PropertyType.GetTypeInfo().IsValueType ? + property.PropertyType.IsValueType ? Activator.CreateInstance(property.PropertyType) : null; diff --git a/tests/Squidex.Infrastructure.Tests/TypeNameRegistryTests.cs b/tests/Squidex.Infrastructure.Tests/TypeNameRegistryTests.cs index db90bc8d2..1b0ff3bfb 100644 --- a/tests/Squidex.Infrastructure.Tests/TypeNameRegistryTests.cs +++ b/tests/Squidex.Infrastructure.Tests/TypeNameRegistryTests.cs @@ -6,7 +6,8 @@ // ========================================================================== using System; -using System.Reflection; +using System.Linq; +using FakeItEasy; using Squidex.Infrastructure.EventSourcing; using Xunit; @@ -26,6 +27,28 @@ namespace Squidex.Infrastructure { } + [Fact] + public void Should_call_provider_from_constructor() + { + var provider = A.Fake(); + + var registry = new TypeNameRegistry(Enumerable.Repeat(provider, 1)); + + A.CallTo(() => provider.Map(registry)) + .MustHaveHappened(); + } + + [Fact] + public void Should_call_provider() + { + var provider = A.Fake(); + + sut.Map(provider); + + A.CallTo(() => provider.Map(sut)) + .MustHaveHappened(); + } + [Fact] public void Should_register_and_retrieve_types() { @@ -50,10 +73,22 @@ namespace Squidex.Infrastructure Assert.Equal(typeof(MyType), sut.GetType("My")); } + [Fact] + public void Should_register_with_provider_from_assembly() + { + sut.Map(new AutoAssembyTypeProvider()); + + Assert.Equal("my", sut.GetName()); + Assert.Equal("my", sut.GetName(typeof(MyType))); + + Assert.Equal(typeof(MyType), sut.GetType("my")); + Assert.Equal(typeof(MyType), sut.GetType("My")); + } + [Fact] public void Should_register_from_assembly() { - sut.MapUnmapped(typeof(TypeNameRegistryTests).GetTypeInfo().Assembly); + sut.MapUnmapped(typeof(TypeNameRegistryTests).Assembly); Assert.Equal("my", sut.GetName()); Assert.Equal("my", sut.GetName(typeof(MyType))); @@ -65,7 +100,7 @@ namespace Squidex.Infrastructure [Fact] public void Should_register_event_type_from_assembly() { - sut.MapUnmapped(typeof(TypeNameRegistryTests).GetTypeInfo().Assembly); + sut.MapUnmapped(typeof(TypeNameRegistryTests).Assembly); Assert.Equal("MyAddedEventV2", sut.GetName()); Assert.Equal("MyAddedEventV2", sut.GetName(typeof(MyAdded))); diff --git a/tools/Migrate_01/SquidexMigrations.cs b/tools/Migrate_01/SquidexMigrations.cs index 085bcf9dd..87fe65348 100644 --- a/tools/Migrate_01/SquidexMigrations.cs +++ b/tools/Migrate_01/SquidexMigrations.cs @@ -9,7 +9,7 @@ using System.Reflection; namespace Migrate_01 { - public static class SquidexMigrations + public sealed class SquidexMigrations { public static readonly Assembly Assembly = typeof(SquidexMigrations).Assembly; }