那么这是怎么回事?
这是背景故事。我正在尝试将.net标准库集成到.net框架产品中。该.net框架产品正在使用旧的Microsoft.Practices框架,该框架使用ObjectBuilder作为服务容器。
ObjectBuilder不能做的现代IoC容器可以做的一件事是处理同一服务类型的多个实现,并在请求时注入该服务类型的IEnumerable
ObjectBuilder在Microsoft.Practices的WebClientSoftwareFactory中使用时,使用IL构造容器的对象并将依赖项注入属性。因此,即使您添加一个单例实例,它仍然会尝试使用IL注入实例的属性。
尝试将.Net Standard类型的List
这是在.net Framework 4.7.2上运行的控制台应用程序
namespace ILTest
{
class Program
{
delegate string Echo(string value);
static void Main(string[] args)
{
Console.WindowWidth = Console.WindowWidth * 2;
EchoOn("1324");
EchoOn(new List<string>());
EchoOn(new NetStandardType());
EchoOn(new List<NetStandardType>()); // this line fails
EchoOn(new GenericNetStandardType<string>());
EchoOn(new GenericNetStandardType<NetStandardType>());
Console.ReadLine();
}
static void EchoOn<T>(T obj)
{
var type = typeof(T);
var value = Guid.NewGuid().ToString();
var echo = CreateEchoMethodOn(obj);
try
{
var echoed = echo(value);
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"Successful il on {type.FullName}");
}
catch(Exception ex)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"Failed il on {type.FullName}");
Console.WriteLine(ex);
}
}
static Echo CreateEchoMethodOn(object obj)
{
var type = obj.GetType();
var method = new DynamicMethod($"Echo_{type.FullName}", typeof(string), new[] { typeof(string) }, type);
var il = method.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ret);
return (Echo)method.CreateDelegate(typeof(Echo));
}
}
}
这些是.net标准2.0库中的类
namespace StandardLib
{
public class NetStandardType
{
}
public class GenericNetStandardType<T>
{
}
}
除List
那么,这又是怎么回事?是.net框架中DynamicMethod中的错误?
答案 0 :(得分:0)
我相信您是由于Code Access Security和透明度规则的复杂工作方式而看到这种行为的。
当您使用列表作为DynamicMethod的类型所有者时,您正在指示运行时使用该类型的CAS选项。当您使用用户定义的类型(在.NET 4上)时,您的类型成员实际上被标记为“关键”,而“列表”和“列表”类型上的成员被标记为“透明”。
由于您尝试从“透明”类型调用“关键”代码,因此出现了所提到的错误。
我相信您可以通过使用以下属性标记具有您的用户类型的程序集来解决此问题:
[assembly: System.Security.SecurityTransparent]
尽管该方法可行,但很难说这是否会带来任何意想不到的后果。我相信这将取决于您的情况。请查看this document以获取更多信息。