Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for Library modules and optimize usage of reflection during startup #4197

Merged
merged 1 commit into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Oqtane.Client/Modules/Admin/ModuleDefinitions/Edit.razor
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="categories" HelpText="Comma delimited list of module categories" ResourceKey="Categories">Categories: </Label>
<div class="col-sm-9">
<input id="categories" class="form-control" @bind="@_categories" maxlength="200" required />
<input id="categories" class="form-control" @bind="@_categories" maxlength="200" />
</div>
</div>
<div class="row mb-1 align-items-center">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@
_containerType = PageState.Site.DefaultContainerType;
_allModuleDefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Site.SiteId);
_moduleDefinitions = _allModuleDefinitions.Where(item => item.Categories.Contains(_category)).ToList();
_categories = _allModuleDefinitions.SelectMany(m => m.Categories.Split(',')).Distinct().ToList();
_categories = _allModuleDefinitions.SelectMany(m => m.Categories.Split(',', StringSplitOptions.RemoveEmptyEntries)).Distinct().Where(item => item != "Library").ToList();
}
}

Expand Down
27 changes: 21 additions & 6 deletions Oqtane.Server/Repository/ModuleDefinitionRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,9 @@ private List<ModuleDefinition> LoadModuleDefinitionsFromAssembly(List<ModuleDefi
{
ModuleDefinition moduledefinition;

Type[] moduletypes = assembly.GetTypes().Where(item => item.GetInterfaces().Contains(typeof(IModule))).ToArray();
Type[] modulecontroltypes = assembly.GetTypes().Where(item => item.GetInterfaces().Contains(typeof(IModuleControl))).ToArray();

foreach (Type modulecontroltype in modulecontroltypes)
{
// Check if type should be ignored
Expand All @@ -299,12 +301,9 @@ private List<ModuleDefinition> LoadModuleDefinitionsFromAssembly(List<ModuleDefi
int index = moduledefinitions.FindIndex(item => item.ModuleDefinitionName == qualifiedModuleType);
if (index == -1)
{
// determine if this module implements IModule
Type moduletype = assembly
.GetTypes()
.Where(item => item.Namespace != null)
.Where(item => item.Namespace == modulecontroltype.Namespace || item.Namespace.StartsWith(modulecontroltype.Namespace + "."))
.FirstOrDefault(item => item.GetInterfaces().Contains(typeof(IModule)));
// determine if this component is part of a module which implements IModule
Type moduletype = moduletypes.FirstOrDefault(item => item.Namespace == modulecontroltype.Namespace);

if (moduletype != null)
{
// get property values from IModule
Expand Down Expand Up @@ -399,6 +398,22 @@ private List<ModuleDefinition> LoadModuleDefinitionsFromAssembly(List<ModuleDefi
moduledefinitions[index] = moduledefinition;
}

// process modules without UI components
foreach (var moduletype in moduletypes.Where(m1 => !modulecontroltypes.Any(m2 => m1.Namespace == m2.Namespace)))
{
// get property values from IModule
var moduleobject = Activator.CreateInstance(moduletype) as IModule;
moduledefinition = moduleobject.ModuleDefinition;
moduledefinition.ModuleDefinitionName = moduletype.Namespace + ", " + moduletype.Assembly.GetName().Name;
moduledefinition.AssemblyName = assembly.GetName().Name;
moduledefinition.Categories = "Library";
moduledefinition.PermissionList = new List<Permission>
{
new Permission(PermissionNames.Utilize, RoleNames.Host, true)
};
moduledefinitions.Add(moduledefinition);
}

return moduledefinitions;
}

Expand Down
29 changes: 12 additions & 17 deletions Oqtane.Server/Repository/ThemeRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using Oqtane.Themes;
using System.Reflection.Metadata;
using Oqtane.Migrations.Master;
using Oqtane.Modules;

namespace Oqtane.Repository
{
Expand Down Expand Up @@ -224,9 +225,11 @@ private List<Theme> LoadThemesFromAssemblies()
private List<Theme> LoadThemesFromAssembly(List<Theme> themes, Assembly assembly)
{
Theme theme;
List<Type> themeTypes = new List<Type>();

Type[] themeTypes = assembly.GetTypes().Where(item => item.GetInterfaces().Contains(typeof(ITheme))).ToArray();
Type[] themeControlTypes = assembly.GetTypes().Where(item => item.GetInterfaces().Contains(typeof(IThemeControl))).ToArray();
Type[] containerControlTypes = assembly.GetTypes().Where(item => item.GetInterfaces().Contains(typeof(IContainerControl))).ToArray();

foreach (Type themeControlType in themeControlTypes)
{
// Check if type should be ignored
Expand All @@ -240,16 +243,9 @@ private List<Theme> LoadThemesFromAssembly(List<Theme> themes, Assembly assembly
int index = themes.FindIndex(item => item.ThemeName == qualifiedThemeType);
if (index == -1)
{
// Find all types in the assembly with the same namespace root
themeTypes = assembly.GetTypes()
.Where(item => !item.IsOqtaneIgnore())
.Where(item => item.Namespace != null)
.Where(item => item.Namespace == themeControlType.Namespace || item.Namespace.StartsWith(themeControlType.Namespace + "."))
.ToList();

// determine if this theme implements ITheme
Type themetype = themeTypes
.FirstOrDefault(item => item.GetInterfaces().Contains(typeof(ITheme)));
// determine if this component is part of a theme which implements ITheme
Type themetype = themeTypes.FirstOrDefault(item => item.Namespace == themeControlType.Namespace);

if (themetype != null)
{
var themeobject = Activator.CreateInstance(themetype) as ITheme;
Expand Down Expand Up @@ -285,6 +281,7 @@ private List<Theme> LoadThemesFromAssembly(List<Theme> themes, Assembly assembly
}
theme = themes[index];

// add theme control
var themecontrolobject = Activator.CreateInstance(themeControlType) as IThemeControl;
theme.Themes.Add(
new ThemeControl
Expand All @@ -296,14 +293,12 @@ private List<Theme> LoadThemesFromAssembly(List<Theme> themes, Assembly assembly
}
);

// containers
Type[] containertypes = themeTypes
.Where(item => item.GetInterfaces().Contains(typeof(IContainerControl))).ToArray();
foreach (Type containertype in containertypes)
if (!theme.Containers.Any())
{
var containerobject = Activator.CreateInstance(containertype) as IThemeControl;
if (theme.Containers.FirstOrDefault(item => item.TypeName == containertype.FullName + ", " + themeControlType.Assembly.GetName().Name) == null)
// add container controls
foreach (Type containertype in containerControlTypes.Where(item => item.Namespace == themeControlType.Namespace))
{
var containerobject = Activator.CreateInstance(containertype) as IThemeControl;
theme.Containers.Add(
new ThemeControl
{
Expand Down