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

*爱你&永不变心* 提交于 2021-02-11 12:57:11

问题


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.


回答1:


Ok, I managed to get this working with the following changes to the IsInheritedFrom method:

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

    var lookup_typeDefinition = lookup.IsGenericType ? lookup.GetGenericTypeDefinition() : null;
    var baseType_typeDefinition = baseType.IsGenericType ? baseType.GetGenericTypeDefinition() : null;

    if (lookup_typeDefinitionCheck == baseType_typeDefinitionCheck) return true;

    return baseType.IsInheritedFrom(lookup);
}

I'm pretty sure that this works on this specific scenario and won't work on others, specially because I'm relying on the base type and lookup being generic otherwise it will return false. However, since I don't plan to use this for any other purpose, it will do.

Now I've ran into another problem with casting the instantiated object, but I will raise another question for that.

Thanks.



来源:https://stackoverflow.com/questions/63120321/c-sharp-validate-that-generic-type-extends-generic-abstract-class-with-type-para

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!