C# 使用.Net标准泛型参数对mscorlib泛型类型调用DynamicMethod会导致MissingMethodException

C# 使用.Net标准泛型参数对mscorlib泛型类型调用DynamicMethod会导致MissingMethodException,c#,.net,generics,dynamic,.net-standard-2.0,C#,.net,Generics,Dynamic,.net Standard 2.0,那么这里发生了什么 这是背景故事。我正在尝试将.net标准库集成到.net framework产品中。此.net framework产品使用旧的Microsoft.Practices框架,该框架使用ObjectBuilder作为服务容器 ObjectBuilder不能做的一件事是处理同一服务类型的多个实现,并在请求时插入该服务类型的IEnumerable。为了处理这个问题,我将手动添加一个列表,并在添加到对象生成器时手动添加每个实现 ObjectBuilder在Microsoft.Practic

那么这里发生了什么

这是背景故事。我正在尝试将.net标准库集成到.net framework产品中。此.net framework产品使用旧的Microsoft.Practices框架,该框架使用ObjectBuilder作为服务容器

ObjectBuilder不能做的一件事是处理同一服务类型的多个实现,并在请求时插入该服务类型的IEnumerable。为了处理这个问题,我将手动添加一个列表,并在添加到对象生成器时手动添加每个实现

ObjectBuilder在Microsoft.Practices的WebClient SoftwareFactory中使用时,使用IL为容器构造对象并将依赖项注入属性。所以,即使您添加了一个单例实例,它仍然会尝试使用IL注入实例的属性

尝试将.Net标准类型的列表添加到ObjectBuilder时出错。我已经能够在控制台应用程序中复制导致错误的原因

这是在.net framework 4.7.2上运行的控制台应用程序

名称空间ILTest
{
班级计划
{
委托字符串回显(字符串值);
静态void Main(字符串[]参数)
{
Console.WindowWidth=Console.WindowWidth*2;
EchoOn(“1324”);
EchoOn(新列表());
EchoOn(新的NetStandardType());
EchoOn(new List());//此行失败
EchoOn(新的GenericNetStandardType());
EchoOn(新的GenericNetStandardType());
Console.ReadLine();
}
静态空洞回波(T obj)
{
var类型=类型(T);
var value=Guid.NewGuid().ToString();
var echo=createechomethon(obj);
尝试
{
var回波=回波(值);
Console.ForegroundColor=ConsoleColor.Green;
WriteLine($“在{type.FullName}上成功的il”);
}
捕获(例外情况除外)
{
Console.ForegroundColor=ConsoleColor.Red;
WriteLine($“在{type.FullName}上失败的il”);
控制台写入线(ex);
}
}
静态Echo CreateEchoMethodOn(对象obj)
{
var type=obj.GetType();
var method=newdynamicmethod($“Echo_{type.FullName}”,typeof(string),new[]{typeof(string)},type);
var il=method.GetILGenerator();
il.Emit(操作码.Ldarg_0);
发射(操作码Ret);
return(Echo)方法.CreateDelegate(typeof(Echo));
}
}
}
这些是.net标准2.0库中的类

名称空间标准库
{
公共类NetStandardType
{
}
公共类GenericNetStandardType
{
}
}
除了列表中的一个之外,所有DynamicMethods都是成功的。该方法失败,并出现MissingMethodException

    • .net框架类型
    • 动态方法成功
  • 名单
    • .net framework泛型类型
    • .net framework通用参数
    • 动态方法成功
  • 网络标准类型
    • .net标准类型
    • 动态方法成功
  • 名单
    • .net framework泛型类型
    • .net标准通用参数
    • 动态方法失败
  • GenericNetStandardType
    • .net标准泛型类型
    • .net framework通用参数
    • 动态方法成功
  • GenericNetStandardType
    • .net标准泛型类型
    • .net标准通用参数
    • 动态方法成功

那么,这里又发生了什么?这是.net framework中DynamicMethod中的一个错误吗?

我相信您会看到这种行为,因为代码访问安全性和透明规则的工作方式非常复杂

当您将列表用作DynamicMethod的类型所有者时,您指示运行时使用该类型的CAS选项。当您使用用户定义的类型(在.NET 4上)时,您的类型成员实际上被标记为“关键”,而“列表”和“列表”类型上的成员被标记为“透明”

因为您试图从“透明”类型调用“关键”代码,所以会出现您提到的错误

我相信您可以通过使用以下属性标记具有用户类型的程序集来解决此问题:

[assembly: System.Security.SecurityTransparent]

虽然这应该行得通,但很难说这是否会产生任何意想不到的后果。我相信这取决于你的情况。请查看以了解更多信息。

我可以用您共享的代码重新编写此代码。但是,我也能够使用与应用程序来自同一程序集的类型来复制它。这看起来不像是一个特定于.NET标准的问题。我能够通过用Hashset替换列表来实现这一点,所以列表有一些特殊之处。我将更深入地挖掘,看看我是否能找出列表中阻止此操作的特殊之处。问题是这些类型不一定是我的。我确实通过创建一个新的.net标准类“解决”了这个问题。公共类安全列表:列表{}
namespace StandardLib
{
    public class NetStandardType
    {
    }

    public class GenericNetStandardType<T>
    {
    }
}
[assembly: System.Security.SecurityTransparent]