Skip to content

Commit

Permalink
PT-12095: Use moduleType specified in the manifest (#2652)
Browse files Browse the repository at this point in the history
fix: Use ModuleType specified in the manifest to resolve multiple IModule from assembly.
  • Loading branch information
ksavosteev authored and OlegoO committed May 8, 2023
1 parent 3207a47 commit 555533c
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 24 deletions.
18 changes: 11 additions & 7 deletions src/VirtoCommerce.Platform.Core/Modularity/ManifestModuleInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public virtual ManifestModuleInfo LoadFromManifest(ModuleManifest manifest)
throw new ArgumentNullException(nameof(manifest));
}

ModuleName = manifest.Id;
ModuleName = manifest.Id;

if (manifest.Dependencies != null)
{
Expand All @@ -64,15 +64,17 @@ public virtual ManifestModuleInfo LoadFromManifest(ModuleManifest manifest)
}

Id = manifest.Id;
Version = SemanticVersion.Parse(string.Join("-", new[] { manifest.Version, manifest.VersionTag }).TrimEnd('-'));
Version = SemanticVersion.Parse(string.Join("-", manifest.Version, manifest.VersionTag).TrimEnd('-'));
VersionTag = manifest.VersionTag;
PlatformVersion = SemanticVersion.Parse(manifest.PlatformVersion);
ReleaseNotes = manifest.ReleaseNotes;
Ref = manifest.PackageUrl;

if (manifest.Dependencies != null)
{
Dependencies.AddRange(manifest.Dependencies.Select(x => new ModuleIdentity(x.Id, SemanticVersion.Parse(x.Version))));
}

if (manifest.Incompatibilities != null)
{
Incompatibilities.AddRange(manifest.Incompatibilities.Select(x => new ModuleIdentity(x.Id, SemanticVersion.Parse(x.Version))));
Expand All @@ -89,14 +91,16 @@ public virtual ManifestModuleInfo LoadFromManifest(ModuleManifest manifest)
Copyright = manifest.Copyright;
Tags = manifest.Tags;
Identity = new ModuleIdentity(Id, Version);
ModuleType = manifest.ModuleType;

if (manifest.Groups != null)
{
Groups.AddRange(manifest.Groups);
}

if(manifest.Apps!=null)
if (manifest.Apps != null)
{
this.Apps.AddRange(manifest.Apps.Select(x => new ManifestAppInfo(x)));
Apps.AddRange(manifest.Apps.Select(x => new ManifestAppInfo(x)));
}

return this;
Expand All @@ -105,12 +109,12 @@ public virtual ManifestModuleInfo LoadFromManifest(ModuleManifest manifest)

public virtual ManifestModuleInfo LoadFromExternalManifest(ExternalModuleManifest manifest, ExternalModuleManifestVersion version)
{
if(manifest == null)
if (manifest == null)
{
throw new ArgumentNullException(nameof(manifest));
}

ModuleName = manifest.Id;
ModuleName = manifest.Id;
if (version.Dependencies != null)
{
foreach (var dependency in version.Dependencies)
Expand Down Expand Up @@ -142,7 +146,7 @@ public virtual ManifestModuleInfo LoadFromExternalManifest(ExternalModuleManifes
LicenseUrl = manifest.LicenseUrl;
ProjectUrl = manifest.ProjectUrl;
IconUrl = manifest.IconUrl;
RequireLicenseAcceptance = manifest.RequireLicenseAcceptance;
RequireLicenseAcceptance = manifest.RequireLicenseAcceptance;
Copyright = manifest.Copyright;
Tags = manifest.Tags;
Identity = new ModuleIdentity(Id, Version);
Expand Down
69 changes: 52 additions & 17 deletions src/VirtoCommerce.Platform.Modules/ModuleInitializer.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
Expand Down Expand Up @@ -34,7 +35,7 @@ public ModuleInitializer(
IConfiguration configuration,
IHostEnvironment hostingEnvironment)
{
_loggerFacade = loggerFacade ?? throw new ArgumentNullException("loggerFacade");
_loggerFacade = loggerFacade ?? throw new ArgumentNullException(nameof(loggerFacade));
_serviceCollection = serviceCollection;
_configuration = configuration;
_hostingEnvironment = hostingEnvironment;
Expand All @@ -47,11 +48,13 @@ public ModuleInitializer(
public void Initialize(ModuleInfo moduleInfo)
{
if (moduleInfo == null)
throw new ArgumentNullException("moduleInfo");
{
throw new ArgumentNullException(nameof(moduleInfo));
}

var manifestModuleInfo = moduleInfo as ManifestModuleInfo;
//Do not initialize modules with errors
if (manifestModuleInfo.Errors.IsNullOrEmpty())
if (moduleInfo is ManifestModuleInfo manifestModuleInfo &&
manifestModuleInfo.Errors.IsNullOrEmpty())
{
try
{
Expand All @@ -62,10 +65,12 @@ public void Initialize(ModuleInfo moduleInfo)
{
configurableModule.Configuration = _configuration;
}

if (moduleInstance is IHasHostEnvironment hasHostEnvironment)
{
hasHostEnvironment.HostEnvironment = _hostingEnvironment;
}

moduleInstance.Initialize(_serviceCollection);
moduleInfo.State = ModuleState.Initialized;
}
Expand All @@ -79,7 +84,9 @@ public void Initialize(ModuleInfo moduleInfo)
public void PostInitialize(ModuleInfo moduleInfo, IApplicationBuilder appBuilder)
{
if (moduleInfo == null)
throw new ArgumentNullException("moduleInfo");
{
throw new ArgumentNullException(nameof(moduleInfo));
}

var moduleInstance = moduleInfo.ModuleInstance;

Expand All @@ -101,15 +108,20 @@ public void PostInitialize(ModuleInfo moduleInfo, IApplicationBuilder appBuilder
/// logs the error using the <see cref="ILogger"/> and throws a <see cref="ModuleInitializeException"/>.
/// This method can be overridden to provide a different behavior.
/// </summary>
/// <param name="moduleInfo">The module metadata where the error happenened.</param>
/// <param name="moduleInfo">The module metadata where the error happened.</param>
/// <param name="exception">The exception thrown that is the cause of the current error.</param>
/// <exception cref="ModuleInitializeException"></exception>
public virtual void HandleModuleInitializationError(ModuleInfo moduleInfo, Exception exception)
{
if (moduleInfo == null)
throw new ArgumentNullException("moduleInfo");
{
throw new ArgumentNullException(nameof(moduleInfo));
}

if (exception == null)
throw new ArgumentNullException("exception");
{
throw new ArgumentNullException(nameof(exception));
}

Exception moduleException;

Expand Down Expand Up @@ -144,20 +156,43 @@ public virtual void HandleModuleInitializationError(ModuleInfo moduleInfo, Excep
protected virtual IModule CreateModule(ModuleInfo moduleInfo)
{
if (moduleInfo == null)
throw new ArgumentNullException("moduleInfo");
{
throw new ArgumentNullException(nameof(moduleInfo));
}

IModule result = null;
var moduleInitializerType = moduleInfo.Assembly.GetTypes().FirstOrDefault(x => typeof(IModule).IsAssignableFrom(x));
if (moduleInitializerType != null && moduleInitializerType != typeof(IModule))
if (!TryResolveModuleTypeFromAssembly(moduleInfo.Assembly, moduleInfo.ModuleType, out var moduleInitializerType) ||
Activator.CreateInstance(moduleInitializerType) is not IModule module)
{
result = (IModule)Activator.CreateInstance(moduleInitializerType);
throw new ModuleInitializeException($"Unable to resolve IModule {moduleInfo.ModuleType} from the assembly {moduleInfo.Assembly.FullName}.");
}
if (result == null)

module.ModuleInfo = moduleInfo as ManifestModuleInfo;

return module;
}

protected virtual bool TryResolveModuleTypeFromAssembly(Assembly moduleAssembly, string moduleType, out Type moduleInitializerType)
{
if (moduleAssembly == null)
{
throw new ArgumentNullException(nameof(moduleAssembly));
}

var moduleInitializerTypes = moduleAssembly.GetTypes().Where(x => typeof(IModule).IsAssignableFrom(x)).ToArray();
if (!moduleInitializerTypes.Any())
{
moduleInitializerType = null;
return false;
}

if (moduleInitializerTypes.Length == 1)
{
throw new ModuleInitializeException($"Unable to retrieve the module type {moduleInitializerType} from the loaded assemblies.You may need to specify a more fully - qualified type name");
moduleInitializerType = moduleInitializerTypes.First();
return true;
}
result.ModuleInfo = moduleInfo as ManifestModuleInfo;
return result;

moduleInitializerType = moduleInitializerTypes.FirstOrDefault(x => x.AssemblyQualifiedName?.StartsWith(moduleType) == true);
return moduleInitializerType != null;
}
}
}

0 comments on commit 555533c

Please sign in to comment.