Я пытаюсь загрузить сборки плагинов, содержащие методы 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)
, параметр не совпадает с типом.