class
SafeTransactionVerification
{
public
void Verify(Assembly assembly)
{
foreach
(Type type
in
assembly.GetTypes())
{
foreach
(MethodInfo info
in
type.GetMethods(BindingFlags.Public
|
BindingFlags.NonPublic
|
BindingFlags.Instance
|
BindingFlags.Static))
{
bool
hasOpen
=
false
;
bool
hasClose
=
false
;
MethodBodyReflector reflector
=
new
MethodBodyReflector(info);
foreach
(ILInstruction il
in
reflector.Instructions)
{
if
(il.GetMethodInfo().DeclaringType
==
typeof
(DbCommand)
&&
il.GetMethodInfo().Name.Equals(
"
OPEN
"
, StringComparison.OrdinalIgnoreCase))
{
hasOpen
=
true
;
continue
;
}
if
(il.GetMethodInfo().DeclaringType
==
typeof
(DbCommand)
&&
il.GetMethodInfo().Name.Equals(
"
COMMIT
"
, StringComparison.OrdinalIgnoreCase))
{
hasClose
=
true
;
continue
;
}
}
if
(hasOpen
&&
hasClose)
continue
;
throw
new
Exception(
"
Transaction is not COMMITTED safely!!
"
);
}
}
}
}
public
class
MethodBodyReflector
{
private
List
<
ILInstruction
>
instructions
=
new
List
<
ILInstruction
>
();
ILGlobals
global
=
new
ILGlobals();
public
MethodBodyReflector(MethodBase info)
{
global
.LoadOpCodes();
if
(info.GetMethodBody()
!=
null
)
{
ConstructInstructions(info);
}
}
///
<summary>
///
所有指令集合
///
</summary>
public
List
<
ILInstruction
>
Instructions
{
get
{
return
instructions;
}
}
private
void
ConstructInstructions(MethodBase info)
{
byte
[] il
=
info.GetMethodBody().GetILAsByteArray();
int
position
=
0
;
while
(position
<
il.Length)
{
ILInstruction instruction
=
ConstructInstruction(info.Module, info, il,
ref
position);
instructions.Add(instruction);
}
}
private
ILInstruction ConstructInstruction(Module module, MethodBase mi,
byte
[] il,
ref
int
position)
{
ILInstruction instruction
=
new
ILInstruction();
//
get the operation code of the current instruction
OpCode code
=
OpCodes.Nop;
ushort
value
=
il[position
++
];
if
(value
!=
0xfe
)
{
code
=
global
.SingleByteOpCodes[(
int
)value];
}
else
{
value
=
il[position
++
];
code
=
global
.MultiByteOpCodes[(
int
)value];
value
=
(
ushort
)(value
|
0xfe00
);
}
instruction.Code
=
code;
instruction.Offset
=
position
-
1
;
int
metadataToken
=
0
;
//
get the operand of the current operation
switch
(code.OperandType)
{
case
OperandType.InlineBrTarget:
metadataToken
=
ReadInt32(il,
ref
position);
metadataToken
+=
position;
instruction.Operand
=
metadataToken;
break
;
case
OperandType.InlineField:
metadataToken
=
ReadInt32(il,
ref
position);
if
(mi
is
ConstructorInfo)
{
instruction.Operand
=
module.ResolveField(metadataToken,
mi.DeclaringType.GetGenericArguments(),
null
);
}
else
{
instruction.Operand
=
module.ResolveField(metadataToken,
mi.DeclaringType.GetGenericArguments(), mi.GetGenericArguments());
}
break
;
case
OperandType.InlineMethod:
metadataToken
=
ReadInt32(il,
ref
position);
try
{
if
(mi
is
ConstructorInfo)
{
instruction.Operand
=
module.ResolveMethod(metadataToken,
mi.DeclaringType.GetGenericArguments(),
null
);
}
else
{
instruction.Operand
=
module.ResolveMethod(metadataToken,
mi.DeclaringType.GetGenericArguments(), mi.GetGenericArguments());
}
}
catch
{
if
(mi
is
ConstructorInfo)
{
instruction.Operand
=
module.ResolveMember(metadataToken,
mi.DeclaringType.GetGenericArguments(),
null
);
}
else
{
instruction.Operand
=
module.ResolveMember(metadataToken,
mi.DeclaringType.GetGenericArguments(), mi.GetGenericArguments());
}
}
break
;
case
OperandType.InlineSig:
metadataToken
=
ReadInt32(il,
ref
position);
instruction.Operand
=
module.ResolveSignature(metadataToken);
break
;
case
OperandType.InlineTok:
metadataToken
=
ReadInt32(il,
ref
position);
try
{
if
(mi
is
ConstructorInfo)
{
instruction.Operand
=
module.ResolveType(metadataToken,
mi.DeclaringType.GetGenericArguments(),
null
);
}
else
{
instruction.Operand
=
module.ResolveType(metadataToken,
mi.DeclaringType.GetGenericArguments(), mi.GetGenericArguments());
}
}
catch
{
}
break
;
case
OperandType.InlineType:
metadataToken
=
ReadInt32(il,
ref
position);
if
(mi
is
MethodInfo)
{
instruction.Operand
=
module.ResolveType(metadataToken,
mi.DeclaringType.GetGenericArguments(), mi.GetGenericArguments());
}
else
if
(mi
is
ConstructorInfo)
{
instruction.Operand
=
module.ResolveType(metadataToken,
mi.DeclaringType.GetGenericArguments(),
null
);
}
else
{
instruction.Operand
=
module.ResolveType(metadataToken);
}
break
;
case
OperandType.InlineI:
{
instruction.Operand
=
ReadInt32(il,
ref
position);
break
;
}
case
OperandType.InlineI8:
{
instruction.Operand
=
ReadInt64(il,
ref
position);
break
;
}
case
OperandType.InlineNone:
{
instruction.Operand
=
null
;
break
;
}
case
OperandType.InlineR:
{
instruction.Operand
=
ReadDouble(il,
ref
position);
break
;
}
case
OperandType.InlineString:
{
metadataToken
=
ReadInt32(il,
ref
position);
instruction.Operand
=
module.ResolveString(metadataToken);
break
;
}
case
OperandType.InlineSwitch:
{
int
count
=
ReadInt32(il,
ref
position);
int
[] casesAddresses
=
new
int
[count];
for
(
int
i
=
0
; i
<
count; i
++
)
{
casesAddresses[i]
=
ReadInt32(il,
ref
position);
}
int
[] cases
=
new
int
[count];
for
(
int
i
=
0
; i
<
count; i
++
)
{
cases[i]
=
position
+
casesAddresses[i];
}
break
;
}
case
OperandType.InlineVar:
{
instruction.Operand
=
ReadUInt16(il,
ref
position);
break
;
}
case
OperandType.ShortInlineBrTarget:
{
instruction.Operand
=
ReadSByte(il,
ref
position)
+
position;
break
;
}
case
OperandType.ShortInlineI:
{
instruction.Operand
=
ReadSByte(il,
ref
position);
break
;
}
case
OperandType.ShortInlineR:
{
instruction.Operand
=
ReadSingle(il,
ref
position);
break
;
}
case
OperandType.ShortInlineVar:
{
instruction.Operand
=
ReadByte(il,
ref
position);
break
;
}
default
:
{
throw
new
Exception(
"
Unknown operand type.
"
);
}
}
return
instruction;
}
private
int
ReadInt16(
byte
[] _il,
ref
int
position)
{
return
((_il[position
++
]
|
(_il[position
++
]
<<
8
)));
}
private
ushort
ReadUInt16(
byte
[] _il,
ref
int
position)
{
return
(
ushort
)((_il[position
++
]
|
(_il[position
++
]
<<
8
)));
}
private
int
ReadInt32(
byte
[] _il,
ref
int
position)
{
return
(((_il[position
++
]
|
(_il[position
++
]
<<
8
))
|
(_il[position
++
]
<<
0x10
))
|
(_il[position
++
]
<<
0x18
));
}
private
ulong
ReadInt64(
byte
[] _il,
ref
int
position)
{
return
(
ulong
)(((_il[position
++
]
|
(_il[position
++
]
<<
8
))
|
(_il[position
++
]
<<
0x10
))
|
(_il[position
++
]
<<
0x18
)
|
(_il[position
++
]
<<
0x20
)
|
(_il[position
++
]
<<
0x28
)
|
(_il[position
++
]
<<
0x30
)
|
(_il[position
++
]
<<
0x38
));
}
private
double
ReadDouble(
byte
[] _il,
ref
int
position)
{
return
(((_il[position
++
]
|
(_il[position
++
]
<<
8
))
|
(_il[position
++
]
<<
0x10
))
|
(_il[position
++
]
<<
0x18
)
|
(_il[position
++
]
<<
0x20
)
|
(_il[position
++
]
<<
0x28
)
|
(_il[position
++
]
<<
0x30
)
|
(_il[position
++
]
<<
0x38
));
}
private
sbyte
ReadSByte(
byte
[] _il,
ref
int
position)
{
return
(
sbyte
)_il[position
++
];
}
private
byte
ReadByte(
byte
[] _il,
ref
int
position)
{
return
(
byte
)_il[position
++
];
}
private
Single ReadSingle(
byte
[] _il,
ref
int
position)
{
return
(Single)(((_il[position
++
]
|
(_il[position
++
]
<<
8
))
|
(_il[position
++
]
<<
0x10
))
|
(_il[position
++
]
<<
0x18
));
}
}
public
class
ILGlobals
{
private
OpCode[] multiByteOpCodes;
private
OpCode[] singleByteOpCodes;
///
<summary>
///
Loads the OpCodes for later use.
///
</summary>
public
void
LoadOpCodes()
{
singleByteOpCodes
=
new
OpCode[
0x100
];
multiByteOpCodes
=
new
OpCode[
0x100
];
FieldInfo[] infoArray1
=
typeof
(OpCodes).GetFields();
for
(
int
num1
=
0
; num1
<
infoArray1.Length; num1
++
)
{
FieldInfo info1
=
infoArray1[num1];
if
(info1.FieldType
==
typeof
(OpCode))
{
OpCode code1
=
(OpCode)info1.GetValue(
null
);
ushort
num2
=
(
ushort
)code1.Value;
if
(num2
<
0x100
)
{
singleByteOpCodes[(
int
)num2]
=
code1;
}
else
{
if
((num2
&
0xff00
)
!=
0xfe00
)
{
throw
new
Exception(
"
Invalid OpCode.
"
);
}
multiByteOpCodes[num2
&
0xff
]
=
code1;
}
}
}
}
///
<summary>
///
Retrieve the friendly name of a type
///
</summary>
///
<param name="typeName">
///
The complete name to the type
///
</param>
///
<returns>
///
The simplified name of the type (i.e. "int" instead f System.Int32)
///
</returns>
public
static
string
ProcessSpecialTypes(
string
typeName)
{
string
result
=
typeName;
switch
(typeName)
{
case
"
System.string
"
:
case
"
System.String
"
:
case
"
String
"
:
result
=
"
string
"
;
break
;
case
"
System.Int32
"
:
case
"
Int
"
:
case
"
Int32
"
:
result
=
"
int
"
;
break
;
}
return
result;
}
public
OpCode[] MultiByteOpCodes
{
get
{
return
multiByteOpCodes; }
}
public
OpCode[] SingleByteOpCodes
{
get
{
return
singleByteOpCodes; }
}
}
public
class
ILInstruction
{
private
OpCode code;
private
object
operand;
private
byte
[] operandData;
private
int
offset;
public
ILInstruction()
{
}
///
<summary>
///
获取指令的类型
///
</summary>
public
ILInstructionType InstructionType
{
get
{
if
(operand
==
null
)
return
ILInstructionType.Unknown;
switch
(code.OperandType)
{
case
OperandType.InlineField:
return
ILInstructionType.Field;
case
OperandType.InlineMethod:
{
if
(operand
is
System.Reflection.MethodInfo)
{
return
ILInstructionType.Method;
}
else
if
(operand
is
System.Reflection.ConstructorInfo)
{
return
ILInstructionType.Ctor;
}
else
{
return
ILInstructionType.Unknown;
}
}
case
OperandType.ShortInlineBrTarget:
case
OperandType.InlineBrTarget:
return
ILInstructionType.Unknown;
case
OperandType.InlineType:
return
ILInstructionType.Unknown;
case
OperandType.InlineString:
return
ILInstructionType.String;
case
OperandType.ShortInlineVar:
return
ILInstructionType.Variable;
case
OperandType.InlineI:
case
OperandType.InlineI8:
case
OperandType.InlineR:
case
OperandType.ShortInlineI:
case
OperandType.ShortInlineR:
return
ILInstructionType.Number;
case
OperandType.InlineTok:
return
ILInstructionType.Reference;
}
return
ILInstructionType.Unknown;
}
}
///
<summary>
///
获取对应的方法
///
</summary>
///
<returns></returns>
public
MethodInfo GetMethodInfo()
{
if
(operand
==
null
)
return
null
;
if
(InstructionType
==
ILInstructionType.Method)
return
(System.Reflection.MethodInfo)operand;
return
null
;
}
///
<summary>
///
获取构造函数
///
</summary>
///
<returns></returns>
public
ConstructorInfo GetConstructorInfo()
{
if
(operand
==
null
)
return
null
;
if
(InstructionType
==
ILInstructionType.Ctor)
return
(System.Reflection.ConstructorInfo)operand;
return
null
;
}
///
<summary>
///
获取域反射
///
</summary>
///
<returns></returns>
public
FieldInfo GetFieldInfo()
{
if
(operand
==
null
)
return
null
;
if
(InstructionType
==
ILInstructionType.Field)
return
((System.Reflection.FieldInfo)operand);
return
null
;
}
///
<summary>
///
获取属性
///
</summary>
///
<returns></returns>
public
string
GetString()
{
return
operand.ToString();
}
///
<summary>
///
Add enough zeros to a number as to be represented on 4 characters
///
</summary>
///
<param name="offset">
///
The number that must be represented on 4 characters
///
</param>
///
<returns>
///
</returns>
private
string
GetExpandedOffset(
long
offset)
{
string
result
=
offset.ToString();
for
(
int
i
=
0
; result.Length
<
4
; i
++
)
{
result
=
"
0
"
+
result;
}
return
result;
}
public
OpCode Code
{
get
{
return
code; }
set
{ code
=
value; }
}
public
object
Operand
{
get
{
return
operand; }
set
{ operand
=
value; }
}
public
byte
[] OperandData
{
get
{
return
operandData; }
set
{ operandData
=
value; }
}
public
int
Offset
{
get
{
return
offset; }
set
{ offset
=
value; }
}
public
override
string
ToString()
{
return
string
.Format(
"
{0} {1} {2}
"
, offset, code.ToString(), operand);
}
}
public
enum
ILInstructionType
{
Unknown,
///
<summary>
///
内部调用的对象
///
</summary>
Field,
///
<summary>
///
内部调用的方法
///
</summary>
Method,
///
<summary>
///
内部调用的构造函数方法
///
</summary>
Ctor,
///
<summary>
///
内部调用的字符串
///
</summary>
String,
///
<summary>
///
[没有确定]内部调用的值对象
///
</summary>
Number,
///
<summary>
///
[没有确定]内部调用的变量
///
</summary>
Variable,
///
<summary>
///
[没有确定]内部调用的引用
///
</summary>
Reference,
///
<summary>
///
集合初始化
///
</summary>
ArrayCtor,
///
<summary>
///
对比表达式
///
</summary>
Compare,
///
<summary>
///
加载值对象
///
</summary>
LoadValue,
///
<summary>
///
加载数组
///
</summary>
LoadArray,
///
<summary>
///
根据位置 加载本地变量
///
</summary>
LoadLocalVariable,
}