Support replacing generic method args

This commit is contained in:
de4dot 2012-11-08 07:05:22 +01:00
parent e600696182
commit c7f4bc83f1

View File

@ -23,6 +23,7 @@ using dot10.DotNet;
namespace de4dot.blocks { namespace de4dot.blocks {
public struct GenericArgsSubstitutor { public struct GenericArgsSubstitutor {
IList<TypeSig> genericArgs; IList<TypeSig> genericArgs;
IList<TypeSig> genericMethodArgs;
bool updated; bool updated;
public static ITypeDefOrRef create(ITypeDefOrRef type, GenericInstSig git) { public static ITypeDefOrRef create(ITypeDefOrRef type, GenericInstSig git) {
@ -117,16 +118,26 @@ namespace de4dot.blocks {
return create(method, git.GenericArguments); return create(method, git.GenericArguments);
} }
// Creates a new method but keeps declaring type as is
public static IMethodDefOrRef create(IMethodDefOrRef method, IList<TypeSig> genericArgs) { public static IMethodDefOrRef create(IMethodDefOrRef method, IList<TypeSig> genericArgs) {
if (method == null || genericArgs == null || genericArgs.Count == 0) return create(method, genericArgs, null);
}
public static IMethodDefOrRef create(IMethodDefOrRef method, GenericInstSig git, IList<TypeSig> genericMethodArgs) {
return create(method, git == null ? null : git.GenericArguments, genericMethodArgs);
}
// Creates a new method but keeps declaring type as is
public static IMethodDefOrRef create(IMethodDefOrRef method, IList<TypeSig> genericArgs, IList<TypeSig> genericMethodArgs) {
if (method == null)
return method;
if ((genericArgs == null || genericArgs.Count == 0) && (genericMethodArgs == null || genericMethodArgs.Count == 0))
return method; return method;
var sig = method.MethodSig; var sig = method.MethodSig;
if (sig == null) if (sig == null)
return method; return method;
var newSig = new GenericArgsSubstitutor(genericArgs).create(sig); var newSig = new GenericArgsSubstitutor(genericArgs, genericMethodArgs).create(sig);
if (newSig == sig) if (newSig == sig)
return method; return method;
@ -135,6 +146,13 @@ namespace de4dot.blocks {
GenericArgsSubstitutor(IList<TypeSig> genericArgs) { GenericArgsSubstitutor(IList<TypeSig> genericArgs) {
this.genericArgs = genericArgs; this.genericArgs = genericArgs;
this.genericMethodArgs = null;
this.updated = false;
}
GenericArgsSubstitutor(IList<TypeSig> genericArgs, IList<TypeSig> genericMethodArgs) {
this.genericArgs = genericArgs;
this.genericMethodArgs = genericMethodArgs;
this.updated = false; this.updated = false;
} }
@ -148,6 +166,7 @@ namespace de4dot.blocks {
return type; return type;
TypeSig result; TypeSig result;
GenericSig varSig;
switch (type.ElementType) { switch (type.ElementType) {
case ElementType.Void: case ElementType.Void:
case ElementType.Boolean: case ElementType.Boolean:
@ -197,8 +216,8 @@ namespace de4dot.blocks {
break; break;
case ElementType.Var: case ElementType.Var:
var varSig = (GenericSig)type; varSig = (GenericSig)type;
if (varSig.Number < (uint)genericArgs.Count) { if (genericArgs != null && varSig.Number < (uint)genericArgs.Count) {
result = genericArgs[(int)varSig.Number]; result = genericArgs[(int)varSig.Number];
updated = true; updated = true;
} }
@ -207,7 +226,13 @@ namespace de4dot.blocks {
break; break;
case ElementType.MVar: case ElementType.MVar:
result = type; varSig = (GenericSig)type;
if (genericMethodArgs != null && varSig.Number < (uint)genericMethodArgs.Count) {
result = genericMethodArgs[(int)varSig.Number];
updated = true;
}
else
result = type;
break; break;
case ElementType.GenericInst: case ElementType.GenericInst: