Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何用Mono.Cecil实现IsAssignableFrom_C#_Mono.cecil - Fatal编程技术网

C# 如何用Mono.Cecil实现IsAssignableFrom

C# 如何用Mono.Cecil实现IsAssignableFrom,c#,mono.cecil,C#,Mono.cecil,我有一个类型我希望在程序集中搜索派生类型 出于性能原因,我尝试使用Mono.Cecil预扫描程序集。扫描和加载所有程序集花费的时间太长,有人建议cecil使用预扫描要快得多,因为只有一小部分可用程序集具有匹配类型 到目前为止,我有以下仅适用于接口的内容 private static IEnumerable<Type> MatchingTypesFromDll<TParent>(string dllPath) { var type = typ

我有一个类型我希望在程序集中搜索派生类型

出于性能原因,我尝试使用Mono.Cecil预扫描程序集。扫描和加载所有程序集花费的时间太长,有人建议cecil使用预扫描要快得多,因为只有一小部分可用程序集具有匹配类型

到目前为止,我有以下仅适用于接口的内容

    private static IEnumerable<Type> MatchingTypesFromDll<TParent>(string dllPath)
    {
        var type = typeof(TParent);
        if (!type.IsInterface)
            throw new Exception("Only interfaces supported");
        try
        {

            var assDef = Mono.Cecil.AssemblyDefinition.ReadAssembly(dllPath);
            var types = assDef.Modules.SelectMany(m => m.GetTypes());
            if (types.Any(t => t.Interfaces.Any(i=>i.FullName == type.FullName)))
            {
                var assembly = Assembly.LoadFrom(dllPath);
                return assembly
                    .GetExportedTypes()
                    .Where(TypeSatisfies<TParent>);
            }
            else
            {
                return new Type[] {};
            }
        }
        catch (Exception e)
        {
            return new Type[] { };
        }

    }

    private static bool TypeSatisfies<TParent>(Type type)
    {
        return typeof (TParent).IsAssignableFrom(type) 
    && !type.IsAbstract 
    && !type.IsInterface;
    }
private static IEnumerable MatchingTypesFromDll(字符串dllPath)
{
var类型=类型(t租金);
if(!type.isiinterface)
抛出新异常(“仅支持接口”);
尝试
{
var assDef=Mono.Cecil.AssemblyDefinition.ReadAssembly(dllPath);
var types=assDef.Modules.SelectMany(m=>m.GetTypes());
if(types.Any(t=>t.Interfaces.Any(i=>i.FullName==type.FullName)))
{
var assembly=assembly.LoadFrom(dllPath);
返回组件
.GetExportedTypes()
.凡(a)段所述;
}
其他的
{
返回新类型[]{};
}
}
捕获(例外e)
{
返回新类型[]{};
}
}
私有静态布尔类型满足(类型)
{
返回类型(t租金)。IsAssignableFrom(类型)
&&!type.IsAbstract
&&!type.i接口;
}

如何将其扩展到基类?

主函数更改为

private static IEnumerable<Type> MatchingTypesFromDll<TBaseType>(string dllPath)
{
   var type = typeof(TBaseType);
   try
   {
      var hasTypes = Mono.Cecil.AssemblyDefinition
          .ReadAssembly(dllPath)
          .Modules
          .Any
          (m =>
           {
              var td = m.Import(type).Resolve();
              return m.GetTypes().Any(t => td.IsAssignableFrom(t));
           });

      if (hasTypes)
      {
          var assembly = Assembly.LoadFrom(dllPath);
          return assembly
         .GetExportedTypes()
         .Where(TypeSatisfies<TBaseType>);
      }
      else
      {
          return new Type[] {};
      }
   }
   catch (Exception)
   {
      return new Type[] { };
   }

}
私有静态IEnumerable匹配TypesFromdll(string dllPath)
{
变量类型=类型(TBaseType);
尝试
{
var hasTypes=Mono.Cecil.AssemblyDefinition
.ReadAssembly(dllPath)
.模块
任何
(m=>
{
var td=m.Import(type).Resolve();
返回m.GetTypes().Any(t=>td.IsAssignableFrom(t));
});
if(hasTypes)
{
var assembly=assembly.LoadFrom(dllPath);
返回组件
.GetExportedTypes()
.凡(a)段所述;
}
其他的
{
返回新类型[]{};
}
}
捕获(例外)
{
返回新类型[]{};
}
}
支持Mono.Cecil的代码是定义IsAssignableFrom的地方,如下所示

static internal class TypeDefinitionExtensions
{
   /// <summary>
   /// Is childTypeDef a subclass of parentTypeDef. Does not test interface inheritance
   /// </summary>
   /// <param name="childTypeDef"></param>
   /// <param name="parentTypeDef"></param>
   /// <returns></returns>
   public static bool IsSubclassOf(this TypeDefinition childTypeDef, TypeDefinition parentTypeDef) => 
      childTypeDef.MetadataToken 
          != parentTypeDef.MetadataToken 
          && childTypeDef
         .EnumerateBaseClasses()
         .Any(b => b.MetadataToken == parentTypeDef.MetadataToken);

   /// <summary>
   /// Does childType inherit from parentInterface
   /// </summary>
   /// <param name="childType"></param>
   /// <param name="parentInterfaceDef"></param>
   /// <returns></returns>
   public static bool DoesAnySubTypeImplementInterface(this TypeDefinition childType, TypeDefinition parentInterfaceDef)
   {
      Debug.Assert(parentInterfaceDef.IsInterface);
      return childType
     .EnumerateBaseClasses()
     .Any(typeDefinition => typeDefinition.DoesSpecificTypeImplementInterface(parentInterfaceDef));
   }

   /// <summary>
   /// Does the childType directly inherit from parentInterface. Base
   /// classes of childType are not tested
   /// </summary>
   /// <param name="childTypeDef"></param>
   /// <param name="parentInterfaceDef"></param>
   /// <returns></returns>
   public static bool DoesSpecificTypeImplementInterface(this TypeDefinition childTypeDef, TypeDefinition parentInterfaceDef)
   {
      Debug.Assert(parentInterfaceDef.IsInterface);
      return childTypeDef
     .Interfaces
     .Any(ifaceDef => DoesSpecificInterfaceImplementInterface(ifaceDef.Resolve(), parentInterfaceDef));
   }

   /// <summary>
   /// Does interface iface0 equal or implement interface iface1
   /// </summary>
   /// <param name="iface0"></param>
   /// <param name="iface1"></param>
   /// <returns></returns>
   public static bool DoesSpecificInterfaceImplementInterface(TypeDefinition iface0, TypeDefinition iface1)
   {
     Debug.Assert(iface1.IsInterface);
     Debug.Assert(iface0.IsInterface);
     return iface0.MetadataToken == iface1.MetadataToken || iface0.DoesAnySubTypeImplementInterface(iface1);
   }

   /// <summary>
   /// Is source type assignable to target type
   /// </summary>
   /// <param name="target"></param>
   /// <param name="source"></param>
   /// <returns></returns>
   public static bool IsAssignableFrom(this TypeDefinition target, TypeDefinition source) 
  => target == source 
     || target.MetadataToken == source.MetadataToken 
     || source.IsSubclassOf(target)
     || target.IsInterface && source.DoesAnySubTypeImplementInterface(target);

   /// <summary>
   /// Enumerate the current type, it's parent and all the way to the top type
   /// </summary>
   /// <param name="klassType"></param>
   /// <returns></returns>
   public static IEnumerable<TypeDefinition> EnumerateBaseClasses(this TypeDefinition klassType)
   {
      for (var typeDefinition = klassType; typeDefinition != null; typeDefinition = typeDefinition.BaseType?.Resolve())
      {
         yield return typeDefinition;
      }
   }
}
静态内部类类型定义扩展
{
/// 
///childTypeDef是parentTypeDef的子类。不测试接口继承性
/// 
/// 
/// 
/// 
公共静态bool IsSubclassOf(此类型定义childTypeDef,类型定义parentTypeDef)=>
childTypeDef.MetadataToken
!=parentTypeDef.MetadataToken
&&儿童类型定义
.EnumerateBaseClasses()
.Any(b=>b.MetadataToken==parentTypeDef.MetadataToken);
/// 
///childType是否从parentInterface继承
/// 
/// 
/// 
/// 
公共静态bool DoesAnySubTypeImplementInterface(此类型定义子类型,类型定义父接口Def)
{
Assert(parentInterfaceDef.IsInterface);
返回子类型
.EnumerateBaseClasses()
.Any(typeDefinition=>typeDefinition.doesspecifictTypeImplementInterface(parentInterfaceDef));
}
/// 
///childType是否直接从parentInterface.Base继承
///未测试childType的类
/// 
/// 
/// 
/// 
公共静态bool不指定TypeImplementInterface(此TypeDefinition childTypeDef,TypeDefinition parentInterfaceDef)
{
Assert(parentInterfaceDef.IsInterface);
返回childTypeDef
.接口
.Any(ifaceDef=>DoesSpecificInterfaceImplementInterface(ifaceDef.Resolve(),parentInterfaceDef));
}
/// 
///接口iface0是否等于或实现接口iface1
/// 
/// 
/// 
/// 
公共静态布尔不指定接口实现接口(类型定义iface0、类型定义iface1)
{
Assert(iface1.IsInterface);
Assert(iface0.IsInterface);
返回iface0.MetadataToken==iface1.MetadataToken | | iface0.DoesAnySubTypeImplementInterface(iface1);
}
/// 
///源类型是否可分配给目标类型
/// 
/// 
/// 
/// 
公共静态bool IsAssignableFrom(此TypeDefinition目标,TypeDefinition源)
=>目标==源
||target.MetadataToken==source.MetadataToken
||来源.IsSubclassOf(目标)
||target.i接口和source.DoesAnySubTypeImplementInterface(目标);
/// 
///枚举当前类型、它的父类型以及一直到顶部的类型
/// 
/// 
/// 
公共静态IEnumerable枚举基类(此类型定义为klassType)
{
for(var typeDefinition=klassType;typeDefinition!=null;typeDefinition=typeDefinition.BaseType?.Resolve())
{
收益率返回类型定义;
}
}
}

当你提到一个类时,你所说的
normal
是什么意思?我指的不是接口。将“normal class”改为“base class”