public override void BuildMethod() { AddStatement.DeclareInterceptedType(field.ContainingType.ResolvedType); Context.Log.WriteTrace(" Adding: var interceptedField = interceptedType.GetField('{0}');", field.Name.Value); Context.Block.Statements.Add( Declare.Variable<FieldInfo>("interceptedField").As( Call.VirtualMethod("GetField", typeof (string)).ThatReturns<FieldInfo>().WithArguments( Constant.Of(field.Name.Value)).On("interceptedType")) ); AddStatement.DeclareArgumentsList(); var funcT = SharpMockTypes.Functions[0]; var funcActualT = new GenericTypeInstanceReference(); funcActualT.GenericType = funcT; funcActualT.GenericArguments.Add(field.Type); var accessor = new AnonymousDelegate(); accessor.Type = funcActualT; accessor.ReturnType = field.Type; accessor.CallingConvention = CallingConvention.HasThis; var accessorBody = new BlockStatement(); var returnActualField = new ReturnStatement(); var actualField = new BoundExpression(); actualField.Type = field.Type; actualField.Definition = field; returnActualField.Expression = actualField; accessorBody.Statements.Add(returnActualField); accessor.Body = accessorBody; Context.Block.Statements.Add( Declare.Variable("local_0", funcActualT).As(accessor) ); AddStatement.DeclareRegistryInterceptor(); AddStatement.DeclareInvocation(); AddStatement.SetArgumentsOnInvocation(); AddStatement.SetOriginalCallOnInvocation(); AddStatement.SetTargetOnInvocationToNull(); Context.Block.Statements.Add( Do(Call.PropertySetter<MemberInfo>("OriginalCallInfo").WithArguments("interceptedField").On("invocation")) ); AddStatement.CallShouldInterceptOnInterceptor(); AddStatement.CallInterceptOnInterceptor(); Context.Block.Statements.Add( Declare.Variable("interceptionResult", field.Type).As( ChangeType.Convert(Call.PropertyGetter<object>("Return").On("invocation")).To(field.Type)) ); Context.Block.Statements.Add(Return.Variable(Locals["interceptionResult"])); }
/// <summary> /// Returns a reference to the closure method. If the method is generic, the reference is to an instantiation, /// using the generic parameters of the current class as arguments. /// </summary> private IMethodReference CreateClosureMethod(AnonymousDelegate anonymousDelegate) { bool isPeerMethod = this.helperMembers != null && !this.anonymousDelegatesThatCaptureLocalsOrParameters.ContainsKey(anonymousDelegate); bool isStaticMethod = isPeerMethod && !this.anonymousDelegatesThatCaptureThis.ContainsKey(anonymousDelegate); var body = new SourceMethodBody(this.host, this.sourceLocationProvider) { Block = anonymousDelegate.Body, LocalsAreZeroed = true }; var counter = isPeerMethod ? this.helperMembers.Count : this.anonymousDelegateCounter++; var prefix = "<"+this.method.Name.Value; prefix += isPeerMethod ? ">p__" : ">b__"; var method = new MethodDefinition() { ContainingTypeDefinition = isPeerMethod ? this.method.ContainingTypeDefinition : this.currentClosureClass, Name = this.host.NameTable.GetNameFor(prefix+counter), Visibility = isPeerMethod ? TypeMemberVisibility.Private : TypeMemberVisibility.Public, Body = body, CallingConvention = isStaticMethod ? CallingConvention.Default : CallingConvention.HasThis, InternFactory = this.host.InternFactory, Parameters = anonymousDelegate.Parameters, Type = anonymousDelegate.ReturnType, IsCil = true, IsStatic = isStaticMethod, IsHiddenBySignature = true, }; body.MethodDefinition = method; if (method.Parameters != null) { foreach (ParameterDefinition parameterDefinition in method.Parameters) parameterDefinition.ContainingSignature = method; } if (isPeerMethod) { this.helperMembers.Add(method); if (this.method.IsGeneric) this.MakeDelegateMethodGeneric(method); method.Attributes = new List<ICustomAttribute>(1); method.Attributes.Add(this.compilerGenerated); } else { this.currentClosureClass.Methods.Add(method); this.isInsideAnonymousMethod = true; this.RewriteChildren(method); this.isInsideAnonymousMethod = false; } IMethodReference methodReference = method; ITypeReference containingTypeDefinitionInstance = method.ContainingTypeDefinition; if (isPeerMethod) containingTypeDefinitionInstance = NamedTypeDefinition.SelfInstance((INamedTypeDefinition)method.ContainingTypeDefinition, this.host.InternFactory); if ((isPeerMethod && method.ContainingTypeDefinition != containingTypeDefinitionInstance) || (!isPeerMethod && this.currentClosureClass != this.currentClosureInstance)) { methodReference = new MethodReference() { CallingConvention = method.CallingConvention, ContainingType = isPeerMethod ? containingTypeDefinitionInstance : this.currentClosureInstance, GenericParameterCount = method.GenericParameterCount, InternFactory = this.host.InternFactory, Name = method.Name, Parameters = methodReference.ParameterCount == 0 ? null : new List<IParameterTypeInformation>(methodReference.Parameters), Type = method.Type, }; } if (!method.IsGeneric) return methodReference; return new GenericMethodInstanceReference() { CallingConvention = method.CallingConvention, ContainingType = method.ContainingTypeDefinition, GenericArguments = new List<ITypeReference>(IteratorHelper.GetConversionEnumerable<IGenericMethodParameter, ITypeReference>(method.GenericParameters)), GenericMethod = methodReference, InternFactory = this.host.InternFactory, Name = method.Name, Parameters = methodReference.ParameterCount == 0 ? null : new List<IParameterTypeInformation>(methodReference.Parameters), Type = method.Type, }; }
public override void BuildMethod() { AddStatement.DeclareInterceptedType(field.ContainingType.ResolvedType); Context.Log.WriteTrace(" Adding: var interceptedField = interceptedType.GetField('{0}');", field.Name.Value); Context.Block.Statements.Add( Declare.Variable<FieldInfo>("interceptedField").As( Call.VirtualMethod("GetField", typeof (string)).ThatReturns<FieldInfo>().WithArguments( Constant.Of(field.Name.Value)).On("interceptedType")) ); AddStatement.DeclareArgumentsList(); AddStatement.AddArgumentToList(Params["assignedValue"]); var actionT = SharpMockTypes.Actions[1]; var actionActualT = new GenericTypeInstanceReference(); actionActualT.GenericType = actionT; actionActualT.GenericArguments.Add(field.Type); var assignment = new AnonymousDelegate(); assignment.Type = actionActualT; assignment.ReturnType = Context.Host.PlatformType.SystemVoid; assignment.CallingConvention = CallingConvention.HasThis; var parameterDefinition = new ParameterDefinition(); parameterDefinition.Index = 0; parameterDefinition.Type = field.Type; parameterDefinition.Name = Context.Host.NameTable.GetNameFor("alteredValue"); parameterDefinition.ContainingSignature = assignment; assignment.Parameters.Add(parameterDefinition); var assignmentBody = new BlockStatement(); var assignActualField = new ExpressionStatement(); var actualField = new TargetExpression(); actualField.Type = field.Type; actualField.Definition = field; var value = new BoundExpression(); value.Type = field.Type; value.Definition = parameterDefinition; var assignValueToField = new Assignment(); assignValueToField.Source = value; assignValueToField.Target = actualField; assignValueToField.Type = field.Type; assignActualField.Expression = assignValueToField; actualField.Type = field.Type; actualField.Definition = field; assignmentBody.Statements.Add(assignActualField); assignmentBody.Statements.Add(new ReturnStatement()); assignment.Body = assignmentBody; Context.Block.Statements.Add( Declare.Variable("local_0", actionActualT).As(assignment) ); AddStatement.DeclareRegistryInterceptor(); AddStatement.DeclareInvocation(); AddStatement.SetArgumentsOnInvocation(); AddStatement.SetOriginalCallOnInvocation(); AddStatement.SetTargetOnInvocationToNull(); Context.Block.Statements.Add( Do(Call.PropertySetter<MemberInfo>("OriginalCallInfo").WithArguments("interceptedField").On("invocation")) ); AddStatement.CallShouldInterceptOnInterceptor(); AddStatement.CallInterceptOnInterceptor(); Context.Block.Statements.Add(Return.Void()); }
/// <summary> /// Visits the specified anonymous delegate. /// </summary> /// <param name="anonymousDelegate">The anonymous delegate.</param> /// <returns></returns> protected virtual IExpression DeepCopy(AnonymousDelegate anonymousDelegate) { //^ requires this.cache.ContainsKey(anonymousDelegate); var pars = new List<IParameterDefinition>(); foreach (var p in anonymousDelegate.Parameters) { var newp = this.DeepCopy(this.GetMutableCopyParamAnonymDeleg(p)); pars.Add(newp); } anonymousDelegate.Parameters = pars; anonymousDelegate.Body = (IBlockStatement)this.Substitute(anonymousDelegate.Body); anonymousDelegate.ReturnType = this.Substitute(anonymousDelegate.ReturnType); anonymousDelegate.Type = this.Substitute(anonymousDelegate.Type); return anonymousDelegate; }
/// <summary> /// Visits the specified anonymous method. /// </summary> /// <param name="anonymousMethod">The anonymous method.</param> public override void Visit(IAnonymousDelegate anonymousMethod) { AnonymousDelegate mutableAnonymousDelegate = new AnonymousDelegate(anonymousMethod); this.resultExpression = this.myCodeCopier.DeepCopy(mutableAnonymousDelegate); }
private IExpression ConvertToAnonymousDelegate(CreateDelegateInstance createDelegateInstance, bool iteratorsHaveNotBeenDecompiled) { IMethodDefinition closureMethod = createDelegateInstance.MethodToCallViaDelegate.ResolvedMethod; if (this.sourceMethodBody.privateHelperMethodsToRemove == null) this.sourceMethodBody.privateHelperMethodsToRemove = new Dictionary<uint, IMethodDefinition>(); IMethodBody closureMethodBody = UnspecializedMethods.GetMethodBodyFromUnspecializedVersion(closureMethod); AnonymousDelegate anonDel = new AnonymousDelegate(); anonDel.CallingConvention = closureMethod.CallingConvention; var unspecializedClosureMethod = UnspecializedMethods.UnspecializedMethodDefinition(closureMethod); this.sourceMethodBody.privateHelperMethodsToRemove[unspecializedClosureMethod.InternedKey] = unspecializedClosureMethod; anonDel.Parameters = new List<IParameterDefinition>(unspecializedClosureMethod.Parameters); for (int i = 0, n = anonDel.Parameters.Count; i < n; i++) { IParameterDefinition closureMethodPar = UnspecializedParameterDefinition(anonDel.Parameters[i]); ParameterDefinition par = new ParameterDefinition(); this.parameterMap.Add(closureMethodPar, par); par.Copy(closureMethodPar, this.host.InternFactory); par.ContainingSignature = anonDel; anonDel.Parameters[i] = par; } var alreadyDecompiledBody = closureMethodBody as SourceMethodBody; ISourceMethodBody anonDelSourceMethodBody = alreadyDecompiledBody; if (alreadyDecompiledBody == null) { var alreadyDecompiledBody2 = closureMethodBody as Microsoft.Cci.MutableCodeModel.SourceMethodBody; if (alreadyDecompiledBody2 == null) { var smb = new SourceMethodBody(closureMethodBody, this.sourceMethodBody.host, this.sourceMethodBody.sourceLocationProvider, this.sourceMethodBody.localScopeProvider, this.sourceMethodBody.options); anonDelSourceMethodBody = smb; anonDel.Body = smb.Block; } else { anonDel.Body = alreadyDecompiledBody2.Block; anonDelSourceMethodBody = alreadyDecompiledBody2; } } else { anonDel.Body = alreadyDecompiledBody.Block; } anonDel.ReturnValueIsByRef = closureMethod.ReturnValueIsByRef; if (closureMethod.ReturnValueIsModified) anonDel.ReturnValueCustomModifiers = new List<ICustomModifier>(closureMethod.ReturnValueCustomModifiers); anonDel.ReturnType = closureMethod.Type; anonDel.Type = createDelegateInstance.Type; if (iteratorsHaveNotBeenDecompiled && unspecializedClosureMethod.ContainingTypeDefinition.IsGeneric && unspecializedClosureMethod.ContainingTypeDefinition.GenericParameterCount == this.sourceMethodBody.MethodDefinition.ContainingTypeDefinition.GenericParameterCount) { var mapper = new GenericTypeParameterMapper(this.host, this.sourceMethodBody.MethodDefinition.ContainingTypeDefinition, unspecializedClosureMethod.ContainingTypeDefinition); mapper.Rewrite(anonDel); } BlockStatement bs = anonDel.Body as BlockStatement; if (bs != null) { var savedReferencedLabels = this.referencedLabels; this.referencedLabels = null; anonDel.Body = this.RemoveCompilationArtifacts(bs); this.referencedLabels = savedReferencedLabels; } IExpression result = anonDel; if (this.sourceMethodBody.MethodDefinition.IsGeneric) { if (unspecializedClosureMethod.IsGeneric) this.genericParameterMapper = new GenericMethodParameterMapper(this.host, this.sourceMethodBody.MethodDefinition, unspecializedClosureMethod); // If the closure method was not generic, then its containing type is generic // and the generic parameter mapper was created when the closure instance creation // was discovered at the beginning of this visitor. if (this.genericParameterMapper != null) { result = this.genericParameterMapper.Visit(result); foreach (var v in this.capturedBinding.Values) { // Do NOT visit any of the parameters in the table because that // will cause them to (possibly) have their types changed. But // they already have the correct type because they are parameters // of the enclosing method. // But the locals are ones that were created by this visitor so // they need their types updated. LocalDefinition ld = v.Definition as LocalDefinition; if (ld != null) { ld.Type = this.genericParameterMapper.Visit(ld.Type); ld.MethodDefinition = this.sourceMethodBody.MethodDefinition; } } } } return result; }
public override IExpression Visit(AnonymousDelegate anonymousDelegate) { return anonymousDelegate; }
/// <summary> /// Rewrites the children of the given anonymous delegate expression. /// </summary> /// <param name="anonymousDelegate"></param> public virtual void RewriteChildren(AnonymousDelegate anonymousDelegate) { this.RewriteChildren((Expression)anonymousDelegate); anonymousDelegate.Parameters = this.Rewrite(anonymousDelegate.Parameters); anonymousDelegate.Body = this.Rewrite((BlockStatement)anonymousDelegate.Body); anonymousDelegate.ReturnType = this.Rewrite(anonymousDelegate.ReturnType); if (anonymousDelegate.ReturnValueIsModified) anonymousDelegate.ReturnValueCustomModifiers =this.Rewrite(anonymousDelegate.ReturnValueCustomModifiers); }
/// <summary> /// Visits the specified anonymous method. /// </summary> /// <param name="anonymousMethod">The anonymous method.</param> public override void Visit(IAnonymousDelegate anonymousMethod) { AnonymousDelegate mutableAnonymousDelegate = anonymousMethod as AnonymousDelegate; if (alwaysMakeACopy || mutableAnonymousDelegate == null) mutableAnonymousDelegate = new AnonymousDelegate(anonymousMethod); this.resultExpression = this.myCodeMutator.Visit(mutableAnonymousDelegate); }
/// <summary> /// Visits the specified anonymous delegate. /// </summary> /// <param name="anonymousDelegate">The anonymous delegate.</param> /// <returns></returns> public virtual IExpression Visit(AnonymousDelegate anonymousDelegate) { this.path.Push(anonymousDelegate); anonymousDelegate.Parameters = this.Visit(anonymousDelegate.Parameters); anonymousDelegate.Body = this.Visit(anonymousDelegate.Body); anonymousDelegate.ReturnType = this.Visit(anonymousDelegate.ReturnType); anonymousDelegate.Type = this.Visit(anonymousDelegate.Type); this.path.Pop(); return anonymousDelegate; }
/// <summary> /// Visits the specified anonymous delegate. /// </summary> /// <param name="anonymousDelegate">The anonymous delegate.</param> /// <returns></returns> public virtual IExpression Visit(AnonymousDelegate anonymousDelegate) { this.path.Push(anonymousDelegate); for (int i = 0, n = anonymousDelegate.Parameters.Count; i < n; i++) anonymousDelegate.Parameters[i] = this.Visit(anonymousDelegate.Parameters[i]); anonymousDelegate.Body = this.Visit(anonymousDelegate.Body); anonymousDelegate.ReturnType = this.Visit(anonymousDelegate.ReturnType); anonymousDelegate.Type = this.Visit(anonymousDelegate.Type); this.path.Pop(); return anonymousDelegate; }