Skip to content
Open
Changes from 2 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
40 changes: 35 additions & 5 deletions src/PlugIns/PlugInManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ public PlugInManager(ICollection<PlugInConfiguration>? configurations, ILoggerFa
public void DiscoverAndRegisterPlugIns()
{
var plugIns = this.DiscoverNewPlugIns();
ValidateNoDuplicateGuids(plugIns);
this.RegisterPlugIns(plugIns);
}

Expand All @@ -100,6 +101,7 @@ public void DiscoverAndRegisterPlugIns()
public void DiscoverAndRegisterPlugIns(Assembly assembly)
{
var plugIns = this.DiscoverNewPlugIns(this.DiscoverPlugIns(assembly));
ValidateNoDuplicateGuids(plugIns);
this.RegisterPlugIns(plugIns);
}

Expand Down Expand Up @@ -304,7 +306,7 @@ public void RegisterPlugIn<TPlugInInterface, TPlugInClass>()
}
else
{
this._logger.LogWarning($"Plugin {typeof(TPlugInClass)} wasn't registered, because it's not an implementation of an interface which is marked with {nameof(PlugInPointAttribute)} or {nameof(CustomPlugInContainerAttribute)}.");
this._logger.LogWarning("Plugin {PlugInClass} wasn't registered, because it's not an implementation of an interface which is marked with PlugInPointAttribute or CustomPlugInContainerAttribute.", typeof(TPlugInClass));
}
}

Expand Down Expand Up @@ -353,6 +355,19 @@ public void ConfigurePlugIn(Guid plugInId, PlugInConfiguration configuration)
}
}

private static void ValidateNoDuplicateGuids(IEnumerable<Type> plugIns)
{
var duplicates = plugIns.GroupBy(t => t.GUID).Where(g => g.Count() > 1).ToList();
if (duplicates.Count == 0)
{
return;
}

var message = string.Join("; ", duplicates.Select(g =>
$"{g.Key} used by {string.Join(", ", g.Select(t => t.FullName))}"));
throw new DuplicatePlugInGuidException(message);
}
Comment thread
eduardosmaniotto marked this conversation as resolved.
Outdated

private Type? GetCustomPlugInPointType(Type interfaceType)
{
if (interfaceType.GetCustomAttribute<CustomPlugInContainerAttribute>() != null)
Expand Down Expand Up @@ -415,13 +430,13 @@ private void ReadConfiguration(PlugInConfiguration configuration, HashSet<string
}
catch (Exception e)
{
this._logger.LogError($"Error while loading external plugin assembly {configuration.ExternalAssemblyName} for plugin {configuration.TypeId}.", e);
this._logger.LogError(e, "Error while loading external plugin assembly {ExternalAssemblyName} for plugin {TypeId}.", configuration.ExternalAssemblyName, configuration.TypeId);
return;
}
}
else if (!string.IsNullOrEmpty(configuration.CustomPlugInSource))
{
this._logger.LogWarning($"Custom plugin source found at plugin configuration: {configuration}");
this._logger.LogWarning("Custom plugin source found at plugin configuration: {Configuration}", configuration);
/* TODO: Implement code signing, if we really need this feature.
Assembly customPlugInAssembly = this.CompileCustomPlugInAssembly(configuration);
this.DiscoverAndRegisterPlugIns(customPlugInAssembly);*/
Expand All @@ -447,7 +462,7 @@ private void ReadConfiguration(PlugInConfiguration configuration, HashSet<string
}
else
{
this._logger.LogWarning($"Unknown plugin type for id {configuration.TypeId}");
this._logger.LogWarning("Unknown plugin type for id {TypeId}", configuration.TypeId);
}
}

Expand Down Expand Up @@ -535,14 +550,29 @@ private void RegisterPlugIns(IEnumerable<Type> plugIns)
}
catch (Exception e)
{
this._logger.LogError(e, $"Couldn't register plugin type {plugIn}");
this._logger.LogError(e, "Couldn't register plugin type {PlugIn}", plugIn);
this._logger.LogError("TODO: Use ServiceContainer");
}

this._lastCreatedPlugIn = null;
}
}

/// <summary>
/// Exception that is thrown when two different plugin types share the same <see cref="GuidAttribute"/>.
/// </summary>
public class DuplicatePlugInGuidException : InvalidOperationException
{
/// <summary>
/// Initializes a new instance of the <see cref="DuplicatePlugInGuidException"/> class.
/// </summary>
/// <param name="message">The message.</param>
public DuplicatePlugInGuidException(string message)
: base(message)
{
}
}

/// <summary>
/// Exception that occurs when the created proxy doesn't implement the expected interface <see cref="IPlugInContainer{TPlugIn}"/>.
/// </summary>
Expand Down