需要在运行时更改SyncBlockIndex和对象的类型。例如:
class A { ... }
class B { ... }
A a = new A();
B b = (?)a;
我知道这很愚蠢,但我认为这是可能的:)
答案 0 :(得分:1)
经过一番调查后,我发现了如何更改SyncBlockIndex和EEClass(实际上是对象的类型)运行时。要执行此操作,请将以下列表中的'n'paste复制到新创建的控制台应用程序并在32-bit
目标上运行(在64-bit
目标UInt32上应更改为UInt64)
专业提示:GCHandle.Alloc().AddrOfPinnedObject()
和其他GCHandle
方法返回的不是对象的地址,而是其他内容,如“同义词”。
using System;
using System.Runtime.InteropServices;
namespace ConsoleTest
{
public static class ObjectGCEx
{
public static unsafe ObjContents *GetGCFields(this object obj)
{
return (ObjContents*)((new ObjPointer { Object = obj }).Pointer);
}
/// <summary>
/// Gets private GC object's fields SyncBlockIndex and EEClass struct pointer
/// </summary>
public static unsafe void GetGCFields(this object obj, out UInt32 syncBlockIndex, out UInt32 eeClass)
{
var contents = (ObjContents*)((new ObjPointer { Object = obj }).Pointer);
syncBlockIndex = contents->syncBlockIndex;
eeClass = contents->eeClass;
}
/// <summary>
/// Gets private GC object's fields SyncBlockIndex and EEClass struct pointer
/// </summary>
public static unsafe UInt32 GetSyncBlockIndex(this object obj)
{
var contents = (ObjContents*)((new ObjPointer { Object = obj }).Pointer);
return contents->syncBlockIndex;
}
/// <summary>
/// Gets private GC object's fields SyncBlockIndex and EEClass struct pointer
/// </summary>
public static unsafe UInt32 GetEEClass(this object obj)
{
var contents = (ObjContents*)((new ObjPointer { Object = obj }).Pointer);
return contents->eeClass;
}
/// <summary>
/// Sets private GC object's field SyncBlockIndex, which is actually index in private GC table.
/// </summary>
/// <param name="obj">Object with SyncBlockIndex to be changed</param>
/// <param name="syncBlockIndex">New value of SyncBlockIndex</param>
public static unsafe void SetSyncBlockIndex(this object obj, UInt32 syncBlockIndex)
{
var contents = (ObjContents*)((new ObjPointer { Object = obj }).Pointer);
contents->syncBlockIndex = syncBlockIndex;
}
/// <summary>
/// Sets private GC object's field EEClass, which is actually describes current class pointer
/// </summary>
/// <param name="obj">Object with SyncBlockIndex to be changed</param>
/// <param name="syncBlockIndex">New value of SyncBlockIndex</param>
public static unsafe void SetEEClass(this object obj, UInt32 eeClass)
{
var contents = (ObjContents*)((new ObjPointer { Object = obj }).Pointer);
contents->eeClass = eeClass;
}
}
[StructLayout(LayoutKind.Explicit)]
public struct ObjPointer
{
[FieldOffset(0)]
internal object Object;
[FieldOffset(4)]
internal uint _pointer;
internal unsafe uint Pointer
{
get {
fixed(uint *pp = &_pointer)
{
return *(uint *)((uint)pp - sizeof(uint)) - sizeof(uint);
}
}
}
}
[StructLayout(LayoutKind.Explicit)]
public struct ObjContents
{
[FieldOffset(0)]
public UInt32 syncBlockIndex;
[FieldOffset(4)]
public UInt32 eeClass;
[FieldOffset(8)]
public byte fieldsStart;
}
public class MainClass
{
public class Person
{
public int x = 123;
public override string ToString()
{
return "From Person";
}
}
public class Customer
{
public override string ToString()
{
return "From Customer";
}
}
public unsafe static void Main(string[] args)
{
var first = new Person();
var second = new Customer();
unsafe
{
Console.WriteLine("type of first: {0}, ToString(): {1}", first.GetType().Name, first);
first.SetEEClass(second.GetEEClass());
Console.WriteLine("type of first: {0}, ToString(): {1}", first.GetType().Name, first);
}
Console.ReadKey();
}
}
}
产地:
type of first: Person, ToString(): From Person
type of first: Customer, ToString(): From Customer
对于同一个对象。此代码不受GC集合保护。
单声道内存不同。它从对象的开始(不是来自.Net Framework的-1字)开始,而SyncBlockIndex是第二个位置,而不是第一个位置。并且SyncBlockInex不是索引,而是指向同步结构的指针。