好的。這不是一個完整的分析,但我懷疑這是足夠的,以確定你是否可以做到這一點,甚至通過交換IL - 據我所知,你不能。
我還上尋找與dotPeek經反編譯的版本,看不出什麼特別之處特定類型/那些特定類型的存在,屬性明智或以其他方式:
namespace System
{
/// <summary>
/// Describes objects that contain both a managed pointer to a location and a runtime representation of the type that may be stored at that location.
/// </summary>
/// <filterpriority>2</filterpriority>
[ComVisible(true)]
[CLSCompliant(false)]
public struct TypedReference
{
所以,這做起來難,我試圖創建一個使用System.Reflection.Emit這樣一類:
namespace NonStorableTest
{
//public class Invalid
//{
// public TypedReference i;
//}
class Program
{
static void Main(string[] args)
{
AssemblyBuilder asmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("EmitNonStorable"),
AssemblyBuilderAccess.RunAndSave);
ModuleBuilder moduleBuilder = asmBuilder.DefineDynamicModule("EmitNonStorable", "EmitNonStorable.dll");
TypeBuilder invalidBuilder = moduleBuilder.DefineType("EmitNonStorable.Invalid",
TypeAttributes.Class | TypeAttributes.Public);
ConstructorBuilder constructorBuilder = invalidBuilder.DefineDefaultConstructor(MethodAttributes.Public);
FieldBuilder fieldI = invalidBuilder.DefineField("i", typeof (TypedReference), FieldAttributes.Public);
invalidBuilder.CreateType();
asmBuilder.Save("EmitNonStorable.dll");
Console.ReadLine();
}
}
}
,當你運行它,拋出一個TypeLoadException,堆棧跟蹤其中的指向你System.Reflection.Emit.TypeBuilder.TermCreateClass。然後我用反編譯器去了,它給了我這個:
[SuppressUnmanagedCodeSecurity]
[SecurityCritical]
[DllImport("QCall", CharSet = CharSet.Unicode)]
private static void TermCreateClass(RuntimeModule module, int tk, ObjectHandleOnStack type);
指向CLR的非託管部分。在這一點上,我不想被擊敗,我挖掘了CLR參考版本的共享源代碼。我不會通過我所做的所有追蹤,以避免在超出所有合理使用範圍的情況下膨脹此答案,但最終,您最終會在MethodTableBuilder :: SetupMethodTable2函數中的\ clr \ src \ vm \ class.cpp中這似乎也設立現場描述符),在那裏你會發現這些行:
// Mark the special types that have embeded stack poitners in them
if (strcmp(name, "ArgIterator") == 0 || strcmp(name, "RuntimeArgumentHandle") == 0)
pClass->SetContainsStackPtr();
和
if (pMT->GetInternalCorElementType() == ELEMENT_TYPE_TYPEDBYREF)
pClass->SetContainsStackPtr();
後者涉及到的\ src \ INC \ cortypeinfo.h找到的信息,即:
// This describes information about the COM+ primitive types
// TYPEINFO(enumName, className, size, gcType, isArray,isPrim, isFloat,isModifier)
[...]
TYPEINFO(ELEMENT_TYPE_TYPEDBYREF, "System", "TypedReference",2*sizeof(void*), TYPE_GC_BYREF, false, false, false, false)
(它實際上是在該名單中唯一ELEMENT_TYPE_TYPEDBYREF型)
ContainsStackPtr()然後依次在各個地方的其他地方使用,以防止使用這些特定的類型,包括的領域 - 從\ SRC \虛擬機\類。 CP,MethodTableBuilder :: InitializeFieldDescs():
// If it is an illegal type, say so
if (pByValueClass->ContainsStackPtr())
{
BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
}
總之:削減了很久,長話短說,它似乎是哪種類型是不可儲存以這種方式實際上是硬的情況下編碼到CLR中,因此如果你想改變列表或者提供一個IL意味着將類型標記爲不可存儲,那麼你幾乎不得不攜帶Mono或者共享源CLR並且剝離你的自己的版本ñ。
如果它*是*硬編碼,順便說一句,我不會感到驚訝。僅僅因爲文檔不想把它放下來並不意味着它不是在編譯器中完成的。 –
我想同樣的事情,但我必須檢查。 –
[CS0611](http://msdn.microsoft.com/en-US/library/bfca7x6z(v = vs80).aspx)是一個相關的錯誤,儘管可能解決方案或者適用於兩者。 – Mir