lundi 27 juillet 2020

C# Validate that generic type extends generic abstract class with type parameters

I've am stuck and I'm looking for some clarification.

I'm having an issue with reflection, I have a WPF app and I've implemented a plugin system as documented here: https://docs.microsoft.com/en-us/dotnet/core/tutorials/creating-app-with-plugin-support

However, I've modified and extended this a bit where my plugins extend an Abstract class instead of an Interface directly because I have some stuff in the constructor.

On my project, the overall structure is the following:

    public abstract class AbstractPlugin<TSignatureFile, TLoadedFile> : 
        IPlugin<TSignatureFile, TLoadedFile> 
        where TSignatureFile : IFileSignature
        where TLoadedFile : LoadedFile { }

    public interface IPlugin<out TSignatureFile, TLoadedFile> 
        where TSignatureFile : IFileSignature
        where TLoadedFile : LoadedFile { }

    public class MyPlugin : AbstractPlugin<MyPluginFileSignature, MyPluginFile { }

    public class MyPluginFileSignature : IFileSignature { }

    public class MyPluginFile : LoadedFile { }

I have then a class I call the "PluginManager" which loads instantiates the plugins. This load and instantiate mechanic is mostly based on this: https://github.com/dotnet/samples/tree/master/core/extensions/AppWithPlugin/AppWithPlugin

The problem I'm having is that the "CreatePlugin" method will list all types found in the assembly until it finds a match and instantiate that, which is not working.

The code is something like this:

foreach (Type type in assembly.GetTypes())
{
   if (type.IsClass && !type.IsAbstract && type.IsInheritedFrom(typeof(AbstractPlugin<IFileSignature, LoadedFile>)))
   {
      AbstractPlugin<IFileSignature, LoadedFile> result = Activator.CreateInstance(type, notificationCallBack) as AbstractPlugin<IFileSignature, LoadedFile>;

      if (result != null)
      {
          count++;
          yield return result;
      }
   }
}

From one of the StackOverflow posts someone recommended creating a extension method on Type which is what that "IsInheritedFrom" is.

Here is the current status of it / mess of me trying to get it to work.

public static bool IsInheritedFrom(this Type type, Type lookup)
{
    var baseType = type.BaseType;
    if (baseType == null)
        return false;

    var isAbstract = lookup.IsAbstract;
    var areEqual = baseType == lookup;
    var isSubClass = type.IsSubclassOf(lookup);

    if (baseType.IsGenericType
            && baseType.GetGenericTypeDefinition() == lookup)
        return true;

    return baseType.IsInheritedFrom(lookup);
}

From this, areEqual and isSubClass always returns false. Any ideas?

Thank you.





Aucun commentaire:

Enregistrer un commentaire