. net Core 3.0 GetMethod с параметром типов не работает - PullRequest
0 голосов
/ 19 января 2020

Я пытаюсь загрузить сборки плагинов, содержащие методы stati c, которые принимают параметр IServiceCollection. Я успешно загрузил сборку и получил тип, который содержит метод (см. Ниже), но если я включил параметр типов, я не смогу получить метод с помощью GetMethod ().

methodInfo = t.GetMethod(mappingConfig.MethodName, BindingFlags.Public | BindingFlags.Static, null, 
  new Type[] { typeof(IServiceCollection) }, null);

Интересно то, что Я могу получить метод, используя

methodInfo = t.GetMethod(mappingConfig.MethodName, BindingFlags.Public | BindingFlags.Static); 

Но если я попытаюсь проверить параметр метода, сравнение типов, похоже, не получится без объяснимой причины.

methodInfo = t.GetMethod(mappingConfig.MethodName, BindingFlags.Public | BindingFlags.Static);

methodInfo.GetParameters()[0].ParameterType == typeof(IServiceCollection); // Returns false
methodInfo.GetParameters()[0].ParameterType.Equals(typeof(IServiceCollection)); // Returns false
methodInfo.GetParameters()[0].ParameterType.IsAssignableFrom(typeof(IServiceCollection)); // Returns false

Stati c Метод выглядит следующим образом:

public static class CustomFieldsEntityMapBuilderPlugin
{
  public static void AddCustomFieldMaps(IServiceCollection services)
  {
    var builder = new EntityMapBuilder(services);
    builder.AddCustomFieldsToMaps<AxEntities.CustomerV3, CRMEntities.lev_customer>();
  }
}

Когда я присваиваю переменным два типа и проверяю их, я не вижу никаких отличий:

var parmType = methodInfo.GetParameters()[0].ParameterType;
var iServiceCollectionType = typeof(IServiceCollection);

parmType.FullName == iServiceCollectionType.FullName; // true
parmType.AssemblyQualifiedName ==  iServiceCollectionType.AssemblyQualifiedName; //true

// parmType.FullName == Microsoft.Extensions.DependencyInjection.IServiceCollection
// iServiceCollectionType.FullName == Microsoft.Extensions.DependencyInjection.IServiceCollection
// parmType.AssemblyQualifiedName == Microsoft.Extensions.DependencyInjection.IServiceCollection, Microsoft.Extensions.DependencyInjection.Abstractions, Version=3.0.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
// iServiceCollectionType.AssemblyQualifiedName == Microsoft.Extensions.DependencyInjection.IServiceCollection, Microsoft.Extensions.DependencyInjection.Abstractions, Version=3.0.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60

Мне кажется, что бы ни вызывало эти типы, которые не считаются равными, вызывают сбой GetMethod ().

Кажется, я что-то упускаю. Любая помощь приветствуется. Я хочу убедиться, что получаю метод с правильным параметром.

Обновление:

Мне удалось воспроизвести эту проблему с помощью небольшого консольного приложения. Если я использую метод в плагине, отражение, по-видимому, будет относиться к типу IServiceCollection по-разному, даже если они принадлежат одной сборке, но могут быть загружены в другом контексте.

Поскольку меня попросили поделиться полным кодом, и я не знаю, как его загрузить, я отправил его в вопросе.

Из TestGetMethod.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.0.2" />
  </ItemGroup>

</Project>

Program.cs

using System;
using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
using System.IO;

namespace TestGetMethod
{
    class Program
    {
        static void Main(string[] args)
        {
            var assembly = Assembly.GetExecutingAssembly();
            Type t = assembly.GetType($"TestGetMethod.{nameof(CustomFieldsEntityMapBuilderPlugin)}");

            MethodInfo methodInfo = t.GetMethod("AddCustomFieldMaps",
                BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(IServiceCollection) }, null);

            Console.WriteLine($"methodInfo.GetParameters()[0].ParameterType == typeof(IServiceCollection) Returns {methodInfo.GetParameters()[0].ParameterType == typeof(IServiceCollection)}");
            Console.WriteLine($"methodInfo.GetParameters()[0].ParameterType.Equals(typeof(IServiceCollection)) Returns {methodInfo.GetParameters()[0].ParameterType.Equals(typeof(IServiceCollection))}");
            Console.WriteLine($"methodInfo.GetParameters()[0].ParameterType.IsAssignableFrom(typeof(IServiceCollection)) Returns {methodInfo.GetParameters()[0].ParameterType.IsAssignableFrom(typeof(IServiceCollection))}");

            assembly = LoadPlugin();
            t = assembly.GetType($"PluginLibrary.{nameof(CustomFieldsEntityMapBuilderPlugin)}");
            methodInfo = t.GetMethod("AddCustomFieldMaps",
                BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(IServiceCollection) }, null);
            Console.WriteLine($"methodInfo.GetParameters()[0].ParameterType == typeof(IServiceCollection) Returns {methodInfo.GetParameters()[0].ParameterType == typeof(IServiceCollection)}");
            Console.WriteLine($"methodInfo.GetParameters()[0].ParameterType.Equals(typeof(IServiceCollection)) Returns {methodInfo.GetParameters()[0].ParameterType.Equals(typeof(IServiceCollection))}");
            Console.WriteLine($"methodInfo.GetParameters()[0].ParameterType.IsAssignableFrom(typeof(IServiceCollection)) Returns {methodInfo.GetParameters()[0].ParameterType.IsAssignableFrom(typeof(IServiceCollection))}");
        }
        static Assembly LoadPlugin()
        {
            string pluginLocation = Path.Combine(Path.GetDirectoryName(typeof(Program).Assembly.Location), "PluginLibrary.dll");
            Console.WriteLine($"Loading commands from: {pluginLocation}");
            PluginLoadContext loadContext = new PluginLoadContext(pluginLocation);
            return loadContext.LoadFromAssemblyName(new AssemblyName(Path.GetFileNameWithoutExtension(pluginLocation)));
        }
    }
}

PluginLoadContext.cs

using System;
using System.Reflection;
using System.Runtime.Loader;

namespace TestGetMethod
{
    class PluginLoadContext : AssemblyLoadContext
    {
        private AssemblyDependencyResolver _resolver;

        public PluginLoadContext(string pluginPath)
        {
            _resolver = new AssemblyDependencyResolver(pluginPath);
        }

        protected override Assembly Load(AssemblyName assemblyName)
        {
            string assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName);
            if (assemblyPath != null)
            {
                return LoadFromAssemblyPath(assemblyPath);
            }

            return null;
        }

        protected override IntPtr LoadUnmanagedDll(string unmanagedDllName)
        {
            string libraryPath = _resolver.ResolveUnmanagedDllToPath(unmanagedDllName);
            if (libraryPath != null)
            {
                return LoadUnmanagedDllFromPath(libraryPath);
            }

            return IntPtr.Zero;
        }
    }
}

CustomFielsEntityMapBuilderPlugin.cs

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Extensions.DependencyInjection;


namespace TestGetMethod
{
    public static class CustomFieldsEntityMapBuilderPlugin
    {
        public static void AddCustomFieldMaps(IServiceCollection services)
        {
            Console.WriteLine("InAddCustomerFieldMaps");
        }
    }
}

Из PluginLibrary.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.0.2" />
  </ItemGroup>

</Project>

CustomFieldsEntityMapBuilderPlugin.cs

using System;
using Microsoft.Extensions.DependencyInjection;

namespace PluginLibrary
{
    public static class CustomFieldsEntityMapBuilderPlugin
    {
        public static void AddCustomFieldMaps(IServiceCollection services)
        {
            Console.WriteLine("InAddCustomerFieldMaps");
        }
    }
}

Я создал PluginLibrary и развернул его в той же самой расположение в качестве сборки TestGetMethod.

Если вы посмотрите в program.main, я загружаю исполняющуюся сборку и получаю класс CustomFieldsEntityMapBuilderPlugin из текущей сборки с пространством имен TestGetMethod. Когда я сравниваю TestGetMethod.CustomFieldsEntityMapBuilderPlugin.AddCustomFieldMaps(IServiceCollection services) тип параметра с typeof(IServiceCollection), параметр того же типа.

Затем я вызываю LoadPlugin(), который создает новый контекст, загружает PluginLibrary.dll в этот контекст и возвращает его как сборку. , Затем я получаю класс CustomFieldsEntityMapBuilderPlugin из сборки PluginLibrary с пространством имен PluginLibrary. Когда я сравниваю PluginLibrary.CustomFieldsEntityMapBuilderPlugin.AddCustomFieldMaps(IServiceCollection services) тип параметра с typeof(IServiceCollection), параметр не совпадает с типом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...