我知道Activator.CreateInstance()可以创建一个新的实例object。IL但我正在寻找一种通过和创建实例的方法Expression。我想我可以创建一个动态 lambda 来创建类型的实例,并缓存 lambda 以加速对象初始化。我对吗?你能帮我吗?
当只从MSBuild 4.0进行发布构建时,我收到"指定的强制转换无效"有效.我在使用Visual Studio 2012的发布版本时对此进行了测试,但没有遇到此问题.我还使用MSBuild 4.0的调试版本对此进行了测试,但没有遇到此问题.
例外: 
码
public abstract class CachedSessionBase : ISessionObject
{
protected Dictionary<MethodBase, Object> _getAndSetCache = new Dictionary<MethodBase, object>();
protected TResult SetAndGet<TResult>(ObjectFactory factory, Func<TResult> func)
{
StackTrace stackTrace = new StackTrace();
var methodBase = stackTrace.GetFrame(1).GetMethod();
if (!_getAndSetCache.ContainsKey(methodBase))
{
_getAndSetCache[methodBase] = func.Invoke();
}
return (TResult)_getAndSetCache[methodBase];
}
Run Code Online (Sandbox Code Playgroud)
错误正在这条线上抛出
return (TResult)_getAndSetCache[methodBase];
Run Code Online (Sandbox Code Playgroud) 查看stfld和stsfld il操作码之间的区别,stfld具有空引用检查,而stsfld则没有.为什么是这样?是因为静态字段在高频堆上,所以它们不是垃圾收集的吗?
http://msdn.microsoft.com/library/system.reflection.emit.opcodes.stfld.aspx
堆栈过渡行为按顺序排列:
- 将对象引用或指针推入堆栈.
- 值被压入堆栈.
- 从堆栈中弹出值和对象引用/指针; 对象中字段的值将替换为提供的值.
stfld指令替换对象字段的值(类型O)或通过指针(类型native int,&或*)替换给定值.Field是一个引用字段成员引用的元数据标记.stfld指令可以具有Unaligned和Volatile之一或两者的前缀.
如果对象引用或指针是空引用并且该字段不是静态的,则抛出NullReferenceException.
如果在元数据中找不到字段,则抛出MissingFieldException.当Microsoft中间语言(MSIL)指令转换为本机代码时,通常会检查此项,而不是在运行时.
我通过Reflection.Emit生成一个带有静态字段num1,num2等的Type.
现在我不知道如何发出代码,将生成的类型中的静态字段的内容加载到静态方法的评估堆栈中.到目前为止我尝试过的是:
generator.Emit(Opcodes.Ldarg, 0);
generator.Emit(Opcodes.Ldfld, "num1");
Run Code Online (Sandbox Code Playgroud)
但显然这不起作用,因为它试图在'this'上加载一个实例字段,而不提供给静态方法.
我应该使用哪种操作码来访问静态字段?
我修改了程序集的字节码以摆脱错误,现在当我尝试使用它时,我得到一个InvalidProgramException.我所做的就是用NOPS代替这个代码:
catch (Exception exception1)
{
Exception exception = exception1;
if (exception as InvalidValueException == null)
{
throw new InvalidGenerationException(2);
}
else
{
throw exception;
}
}
Run Code Online (Sandbox Code Playgroud)
IL之前:
catch [mscorlib]System.Exception
{
IL_022f: stloc.s exception
IL_0231: ldloc.s exception
IL_0233: isinst Custom.InvalidValueException
IL_0238: brfalse.s IL_023d
IL_023a: ldloc.s exception
IL_023c: throw
IL_023d: ldc.i4.1
IL_023e: newobj instance void Custom.InvalidGenerationException ...
IL_0243: throw
}
Run Code Online (Sandbox Code Playgroud)
IL之后:
catch [mscorlib]System.Exception
{
IL_022f: nop
IL_0230: nop
IL_0231: nop
IL_0232: nop
IL_0233: nop
IL_0234: nop
IL_0235: nop
IL_0236: nop
IL_0237: nop …Run Code Online (Sandbox Code Playgroud) 今天我很震惊,有比较内心的倾向Buffer.BlockCopy,Array.CopyTo. 我很好奇,看看是否在幕后Array.CopyTo被召唤Buffer.BlockCopy.这背后没有实际用途,我只想进一步了解C#语言及其实现方式.不要跳枪并指责我微观优化,但你可以指责我好奇!
当我在mscorlib.dll上运行ILdasm时,我收到了这个 Array.CopyTo
.method public hidebysig newslot virtual final
instance void CopyTo(class System.Array 'array',
int32 index) cil managed
{
// Code size 0 (0x0)
} // end of method Array::CopyTo
Run Code Online (Sandbox Code Playgroud)
这个 Buffer.BlockCopy
.method public hidebysig static void BlockCopy(class System.Array src,
int32 srcOffset,
class System.Array dst,
int32 dstOffset,
int32 count) cil managed internalcall
{
.custom instance void System.Security.SecuritySafeCriticalAttribute::.ctor() = ( 01 00 00 00 )
} // end of method Buffer::BlockCopy
Run Code Online (Sandbox Code Playgroud)
坦率地说,这令我感到困惑.我从未在我没有创建的dll/exe上运行ILdasm.这是否意味着我将无法看到这些功能是如何实现的?搜索周围只显示了一个stackoverflow问题 …
我试图通过我们的编译器和带有Windows 8的.NET 4.5来解决问题的根源.我已将其简化为一小段代码,并想知道是否有人对此问题有任何了解.我写了一些C#,它使用反射生成一个显示问题的程序集.C#(在VS2010解决方案中这里https://dl.dropbox.com/u/10931452/sdata.zip)位于本文的底部.它创建了一个类'sdata',并为其添加了一个名为'blank16'的静态字段.然后它创建一个静态构造函数来初始化该字段.生成的可执行文件将写入c:\ temp\sdatatest.exe.当sdatatest在.NET 4.5下运行时,它会生成:
未处理的异常:System.TypeInitializationException:'sdata'的类型初始值设定项引发异常.---> System.AccessViolationException:尝试读取或写入受保护的内存.这通常表明其他内存已损坏.在sdata..cctor()---内部异常堆栈跟踪结束---在sdata.main()
在安装了.NET 4.5的Windows 7上运行时,它会运行.当在早期的.NET框架上运行时,它也会运行 - 并且已经运行了十年.
产生的IL看起来有效:

JITed x86代码看起来也非常有效:

edi的值看起来像加载的可执行文件中的位置而不是托管内存空间中的位置,如果它是只读的,则可以解释访问冲突.为什么这会在Windows 8上发生变化?
C#生成sdatatest程序集:
using System;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;
namespace sdata
{
class Program
{
static void Main( string[] args )
{
AssemblyName name = new AssemblyName( );
name.Name = "sdatatest.exe";
string exepath = "c:\\temp\\" + name.Name;
name.CodeBase = "file:://" + exepath;
AssemblyBuilder ass_bldr = Thread.GetDomain( ).DefineDynamicAssembly( name, AssemblyBuilderAccess.RunAndSave, Path.GetDirectoryName( exepath ));
ModuleBuilder module_bldr = ass_bldr.DefineDynamicModule( Path.GetFileName( exepath ), …Run Code Online (Sandbox Code Playgroud) 让我来描述我的问题 - 我有一个包含非托管句柄的结构(让我们称之为Mem).每当复制时,我都需要这个句柄来调用一个特定的方法(比如说"保留"或者保持引用计数).
换句话说,我需要一个在内部维护引用计数的结构(我在外部也有一个机制,但需要一种方法来调用该机制).
不幸的是,C#不允许我以任何方式这样做.
我也不能使Mem成为一个类,因为我将这些结构的数组传递给非托管代码,我不希望在传入它们之前逐个转换它们(只是引脚和传递).
有没有人知道可以应用于添加此行为的任何变通方法(IL Weaving等)?我相信IL不会阻止我这样做,只有C#,对吗?
我很乐意回答有关框架和限制的任何问题,但我不是在寻找 - "请改变你的设计"或"不要使用C#这个"答案,非常感谢.
在Visual Studio C#编辑器中,当您右键单击关键字"double"或标识符"Double"并选择"Go to Definition"时,VS将告诉您"NaN"已声明并初始化如下:
public const double NaN = 0.0 / 0.0;
//public const double NegativeInfinity = -1.0 / 0.0;
//public const double PositiveInfinity = 1.0 / 0.0;
Run Code Online (Sandbox Code Playgroud)
但是,从mscorlib.dll中反汇编的System.Double的源代码讲述了一个不同的故事:
public const double NaN = double.NaN;
//public const double NegativeInfinity = double.NegativeInfinity;
//public const double PositiveInfinity = double.PositiveInfinity;
Run Code Online (Sandbox Code Playgroud)
当然,.NET不允许使用对自身的引用(循环定义)或带有对自身的引用的实例字段来初始化const字段(不允许使用对实例字段的引用来初始化实例字段),而可以通过引用自身来初始化静态字段,这显然不是这里的情况.
现在,大多数.NET书籍教授的第一件事就是标识符"Double"和关键字"double"都指向相同的类型(int和Int32,string和String等相同),并且快速查看在IL应该足以证明任何怀疑这一点的人.
考虑到这一点,为什么System.Double类型可以通过将double类型的常量字段初始化为自身而逃脱?这是不是意味着,
...适用于仅由.NET程序员编写的代码的规则不适用于内部.NET代码?......反汇编者弄错了?......"双"和"双"并不是真的相同?
我在c#中有这个程序:
using System;
class Program
{
public static void Main()
{
int i = 4;
double d = 12.34;
double PI = Math.PI;
string name = "Ehsan";
}
}
Run Code Online (Sandbox Code Playgroud)
当我编译它时,以下是编译器为Main生成的IL:
.method public hidebysig static void Main() cil managed
{
.entrypoint
// Code size 30 (0x1e)
.maxstack 1
.locals init (int32 V_0,
float64 V_1,
float64 V_2,
string V_3)
IL_0000: nop
IL_0001: ldc.i4.4
IL_0002: stloc.0
IL_0003: ldc.r8 12.34
IL_000c: stloc.1
IL_000d: ldc.r8 3.1415926535897931
IL_0016: stloc.2
IL_0017: ldstr "Ehsan"
IL_001c: stloc.3
IL_001d: ret …Run Code Online (Sandbox Code Playgroud)