private static TypeNodeList DuplicateTypeParameterList(TypeNodeList typeParameters, int offsetIndex, TypeNode declaringType) { if (typeParameters == null) return null; Duplicator dup = new Duplicator(declaringType.DeclaringModule, null); dup.FindTypesToBeDuplicated(typeParameters); TypeNodeList result = dup.VisitTypeParameterList(typeParameters); for (int i = 0; i < result.Count; i++) { TypeNode tn = result[i]; tn.DeclaringType = declaringType; tn.DeclaringModule = declaringType.DeclaringModule; ITypeParameter tp = (ITypeParameter) tn; tp.ParameterListIndex = offsetIndex + i; tp.DeclaringMember = declaringType; } return result; }
private Class CreateWrapperClass(Class c) { var flags = WrapperTypeFlags(c); var wrapper = new Class(this.assemblyBeingRewritten, null, null, flags, null, c.Name, SystemTypes.Object, null, null); RewriteHelper.TryAddCompilerGeneratedAttribute(wrapper); if (c.TemplateParameters != null) { Duplicator d = new Duplicator(this.assemblyBeingRewritten, wrapper); d.FindTypesToBeDuplicated(c.TemplateParameters); var templateParams = CopyTypeParameterList(wrapper, c, d); wrapper.TemplateParameters = templateParams; wrapper.IsGeneric = true; } return wrapper; }
private Method CreateWrapperMethod(bool virtcall, TypeNode virtcallConstraint, Method templateMethod, TypeNode templateType, TypeNode wrapperType, Method methodWithContract, Method instanceMethod, SourceContext callingContext) { bool isProtected = IsProtected(templateMethod); Identifier name = templateMethod.Name; if (virtcall) { if (virtcallConstraint != null) { name = Identifier.For("CV$" + name.Name); } else { name = Identifier.For("V$" + name.Name); } } else { name = Identifier.For("NV$" + name.Name); } Duplicator dup = new Duplicator(this.assemblyBeingRewritten, wrapperType); TypeNodeList typeParameters = null; TypeNodeList typeParameterFormals = new TypeNodeList(); TypeNodeList typeParameterActuals = new TypeNodeList(); if (templateMethod.TemplateParameters != null) { dup.FindTypesToBeDuplicated(templateMethod.TemplateParameters); typeParameters = dup.VisitTypeParameterList(templateMethod.TemplateParameters); for (int i = 0; i < typeParameters.Count; i++) { typeParameterFormals.Add(typeParameters[i]); typeParameterActuals.Add(templateMethod.TemplateParameters[i]); } } ITypeParameter constraintTypeParam = null; if (virtcallConstraint != null) { if (typeParameters == null) { typeParameters = new TypeNodeList(); } var constraint = templateMethod.DeclaringType; var classConstraint = constraint as Class; if (classConstraint != null) { var classParam = new MethodClassParameter(); classParam.BaseClass = classConstraint; classParam.Name = Identifier.For("TC"); classParam.DeclaringType = wrapperType; typeParameters.Add(classParam); constraintTypeParam = classParam; } else { var mtp = new MethodTypeParameter(); Interface intf = constraint as Interface; if (intf != null) { mtp.Interfaces.Add(intf); } mtp.Name = Identifier.For("TC"); mtp.DeclaringType = wrapperType; typeParameters.Add(mtp); constraintTypeParam = mtp; } } var consolidatedTemplateTypeParameters = templateType.ConsolidatedTemplateParameters; if (consolidatedTemplateTypeParameters != null && consolidatedTemplateTypeParameters.Count > 0) { var consolidatedWrapperTypeParameters = wrapperType.ConsolidatedTemplateParameters; for (int i = 0; i < consolidatedTemplateTypeParameters.Count; i++) { typeParameterFormals.Add(consolidatedWrapperTypeParameters[i]); typeParameterActuals.Add(consolidatedTemplateTypeParameters[i]); } } Specializer spec = null; if (typeParameterActuals.Count > 0) { spec = new Specializer(this.assemblyBeingRewritten, typeParameterActuals, typeParameterFormals); } var parameters = new ParameterList(); var asTypeConstraintTypeParam = constraintTypeParam as TypeNode; if (!isProtected && !templateMethod.IsStatic) { TypeNode thisType = GetThisTypeInstance(templateType, wrapperType, asTypeConstraintTypeParam); parameters.Add(new Parameter(Identifier.For("@this"), thisType)); } for (int i = 0; i < templateMethod.Parameters.Count; i++) { parameters.Add((Parameter)dup.VisitParameter(templateMethod.Parameters[i])); } var retType = dup.VisitTypeReference(templateMethod.ReturnType); if (spec != null) { parameters = spec.VisitParameterList(parameters); retType = spec.VisitTypeReference(retType); } var wrapperMethod = new Method(wrapperType, null, name, parameters, retType, null); RewriteHelper.TryAddCompilerGeneratedAttribute(wrapperMethod); if (isProtected) { wrapperMethod.Flags = templateMethod.Flags & ~MethodFlags.Abstract; wrapperMethod.CallingConvention = templateMethod.CallingConvention; } else { wrapperMethod.Flags |= MethodFlags.Static | MethodFlags.Assembly; } if (constraintTypeParam != null) { constraintTypeParam.DeclaringMember = wrapperMethod; } if (typeParameters != null) { if (spec != null) { typeParameters = spec.VisitTypeParameterList(typeParameters); } wrapperMethod.IsGeneric = true; wrapperMethod.TemplateParameters = typeParameters; } // create body var sl = new StatementList(); Block b = new Block(sl); // insert requires AddRequiresToWrapperMethod(wrapperMethod, b, methodWithContract); // create original call var targetType = templateType; if (isProtected) { // need to use base chain instantiation of target type. targetType = instanceMethod.DeclaringType; } else { if (targetType.ConsolidatedTemplateParameters != null && targetType.ConsolidatedTemplateParameters.Count > 0) { // need selfinstantiation targetType = targetType.GetGenericTemplateInstance(this.assemblyBeingRewritten, wrapperType.ConsolidatedTemplateParameters); } } Method targetMethod = GetMatchingMethod(targetType, templateMethod, wrapperMethod); if (targetMethod.IsGeneric) { if (typeParameters.Count > targetMethod.TemplateParameters.Count) { // omit the extra constrained type arg. TypeNodeList origArgs = new TypeNodeList(); for (int i = 0; i < targetMethod.TemplateParameters.Count; i++) { origArgs.Add(typeParameters[i]); } targetMethod = targetMethod.GetTemplateInstance(wrapperType, origArgs); } else { targetMethod = targetMethod.GetTemplateInstance(wrapperType, typeParameters); } } MethodCall call; NodeType callType = virtcall ? NodeType.Callvirt : NodeType.Call; if (isProtected) { var mb = new MemberBinding(wrapperMethod.ThisParameter, targetMethod); var elist = new ExpressionList(wrapperMethod.Parameters.Count); for (int i = 0; i < wrapperMethod.Parameters.Count; i++) { elist.Add(wrapperMethod.Parameters[i]); } call = new MethodCall(mb, elist, callType); } else if (templateMethod.IsStatic) { var elist = new ExpressionList(wrapperMethod.Parameters.Count); for (int i = 0; i < wrapperMethod.Parameters.Count; i++) { elist.Add(wrapperMethod.Parameters[i]); } call = new MethodCall(new MemberBinding(null, targetMethod), elist, callType); } else { var mb = new MemberBinding(wrapperMethod.Parameters[0], targetMethod); var elist = new ExpressionList(wrapperMethod.Parameters.Count - 1); for (int i = 1; i < wrapperMethod.Parameters.Count; i++) { elist.Add(wrapperMethod.Parameters[i]); } call = new MethodCall(mb, elist, callType); } if (constraintTypeParam != null) { call.Constraint = asTypeConstraintTypeParam; } if (HelperMethods.IsVoidType(templateMethod.ReturnType)) { sl.Add(new ExpressionStatement(call,callingContext)); sl.Add(new Return(callingContext)); } else { sl.Add(new Return(call,callingContext)); } wrapperMethod.Body = b; wrapperType.Members.Add(wrapperMethod); return wrapperMethod; }
private Class MakeContractException() { Class contractExceptionType; #region If we're rewriting an assembly for v4 or above and it *isn't* Silverlight (so serialization support is needed), then use new embedded dll as the type if (4 <= TargetPlatform.MajorVersion) { var iSafeSerializationData = SystemTypes.SystemAssembly.GetType(Identifier.For("System.Runtime.Serialization"), Identifier.For("ISafeSerializationData")) as Interface; if (iSafeSerializationData != null) { // Just much easier to write the C# and have the compiler generate everything than to try and create it all manually System.Reflection.Assembly embeddedAssembly; Stream embeddedAssemblyStream; embeddedAssembly = System.Reflection.Assembly.GetExecutingAssembly(); embeddedAssemblyStream = embeddedAssembly.GetManifestResourceStream("Microsoft.Contracts.Foxtrot.InternalException.dll"); byte[] data = new byte[0]; using (var br = new BinaryReader(embeddedAssemblyStream)) { var len = embeddedAssemblyStream.Length; if (len < Int32.MaxValue) data = br.ReadBytes((int)len); AssemblyNode assemblyNode = AssemblyNode.GetAssembly(data, TargetPlatform.StaticAssemblyCache, true, false, true); contractExceptionType = assemblyNode.GetType(Identifier.For(""), Identifier.For("ContractException")) as Class; } if (contractExceptionType == null) throw new RewriteException("Tried to create the ContractException type from the embedded dll, but failed"); var d = new Duplicator(this.targetAssembly, this.RuntimeContractType); d.FindTypesToBeDuplicated(new TypeNodeList(contractExceptionType)); var ct = d.Visit(contractExceptionType); contractExceptionType = (Class)ct; contractExceptionType.Flags |= TypeFlags.NestedPrivate; this.RuntimeContractType.Members.Add(contractExceptionType); return contractExceptionType; } } #endregion contractExceptionType = new Class(this.targetAssembly, this.RuntimeContractType, new AttributeList(), TypeFlags.Class | TypeFlags.NestedPrivate | TypeFlags.Serializable, null, Identifier.For("ContractException"), SystemTypes.Exception, null, null); RewriteHelper.TryAddCompilerGeneratedAttribute(contractExceptionType); var kindField = new Field(contractExceptionType, null, FieldFlags.Private, Identifier.For("_Kind"), contractNodes.ContractFailureKind, null); var userField = new Field(contractExceptionType, null, FieldFlags.Private, Identifier.For("_UserMessage"), SystemTypes.String, null); var condField = new Field(contractExceptionType, null, FieldFlags.Private, Identifier.For("_Condition"), SystemTypes.String, null); contractExceptionType.Members.Add(kindField); contractExceptionType.Members.Add(userField); contractExceptionType.Members.Add(condField); #region Constructor for setting the fields var parameters = new ParameterList(); var kindParam = new Parameter(Identifier.For("kind"), this.contractNodes.ContractFailureKind); var failureParam = new Parameter(Identifier.For("failure"), SystemTypes.String); var usermsgParam = new Parameter(Identifier.For("usermsg"), SystemTypes.String); var conditionParam = new Parameter(Identifier.For("condition"), SystemTypes.String); var innerParam = new Parameter(Identifier.For("inner"), SystemTypes.Exception); parameters.Add(kindParam); parameters.Add(failureParam); parameters.Add(usermsgParam); parameters.Add(conditionParam); parameters.Add(innerParam); var body = new Block(new StatementList()); var ctor = new InstanceInitializer(contractExceptionType, null, parameters, body); ctor.Flags |= MethodFlags.Public | MethodFlags.HideBySig; ctor.CallingConvention = CallingConventionFlags.HasThis; body.Statements.Add(new ExpressionStatement(new MethodCall(new MemberBinding(ctor.ThisParameter, contractExceptionType.BaseClass.GetConstructor(SystemTypes.String, SystemTypes.Exception)), new ExpressionList(failureParam, innerParam)))); body.Statements.Add(new AssignmentStatement(new MemberBinding(ctor.ThisParameter, kindField), kindParam)); body.Statements.Add(new AssignmentStatement(new MemberBinding(ctor.ThisParameter, userField), usermsgParam)); body.Statements.Add(new AssignmentStatement(new MemberBinding(ctor.ThisParameter, condField), conditionParam)); body.Statements.Add(new Return()); contractExceptionType.Members.Add(ctor); #endregion if (SystemTypes.SerializationInfo != null && SystemTypes.SerializationInfo.BaseClass != null) { // Silverlight (e.g.) is a platform that doesn't support serialization. So check to make sure the type really exists. // var baseCtor = SystemTypes.Exception.GetConstructor(SystemTypes.SerializationInfo, SystemTypes.StreamingContext); if (baseCtor != null) { #region Deserialization Constructor parameters = new ParameterList(); var info = new Parameter(Identifier.For("info"), SystemTypes.SerializationInfo); var context = new Parameter(Identifier.For("context"), SystemTypes.StreamingContext); parameters.Add(info); parameters.Add(context); body = new Block(new StatementList()); ctor = new InstanceInitializer(contractExceptionType, null, parameters, body); ctor.Flags |= MethodFlags.Private | MethodFlags.HideBySig; ctor.CallingConvention = CallingConventionFlags.HasThis; // : base(info, context) body.Statements.Add(new ExpressionStatement(new MethodCall(new MemberBinding(ctor.ThisParameter, baseCtor), new ExpressionList(info, context)))); // _Kind = (ContractFailureKind)info.GetInt32("Kind"); var getInt32 = SystemTypes.SerializationInfo.GetMethod(Identifier.For("GetInt32"), SystemTypes.String); body.Statements.Add(new AssignmentStatement( new MemberBinding(new This(), kindField), new MethodCall(new MemberBinding(info, getInt32), new ExpressionList(new Literal("Kind", SystemTypes.String))) )); // _UserMessage = info.GetString("UserMessage"); var getString = SystemTypes.SerializationInfo.GetMethod(Identifier.For("GetString"), SystemTypes.String); body.Statements.Add(new AssignmentStatement( new MemberBinding(new This(), userField), new MethodCall(new MemberBinding(info, getString), new ExpressionList(new Literal("UserMessage", SystemTypes.String))) )); // _Condition = info.GetString("Condition"); body.Statements.Add(new AssignmentStatement( new MemberBinding(new This(), condField), new MethodCall(new MemberBinding(info, getString), new ExpressionList(new Literal("Condition", SystemTypes.String))) )); body.Statements.Add(new Return()); contractExceptionType.Members.Add(ctor); #endregion #region GetObjectData var securityCriticalCtor = SystemTypes.SecurityCriticalAttribute.GetConstructor(); var securityCriticalAttribute = new AttributeNode(new MemberBinding(null, securityCriticalCtor), null, System.AttributeTargets.Method); var attrs = new AttributeList(securityCriticalAttribute); parameters = new ParameterList(); info = new Parameter(Identifier.For("info"), SystemTypes.SerializationInfo); context = new Parameter(Identifier.For("context"), SystemTypes.StreamingContext); parameters.Add(info); parameters.Add(context); body = new Block(new StatementList()); var getObjectDataName = Identifier.For("GetObjectData"); var getObjectData = new Method(contractExceptionType, attrs, getObjectDataName, parameters, SystemTypes.Void, body); getObjectData.CallingConvention = CallingConventionFlags.HasThis; // public override getObjectData.Flags = MethodFlags.Public | MethodFlags.Virtual; // base.GetObjectData(info, context); var baseGetObjectData = SystemTypes.Exception.GetMethod(getObjectDataName, SystemTypes.SerializationInfo, SystemTypes.StreamingContext); body.Statements.Add(new ExpressionStatement( new MethodCall(new MemberBinding(new This(), baseGetObjectData), new ExpressionList(info, context), NodeType.Call, SystemTypes.Void) )); // info.AddValue("Kind", _Kind); var addValueObject = SystemTypes.SerializationInfo.GetMethod(Identifier.For("AddValue"), SystemTypes.String, SystemTypes.Object); body.Statements.Add(new ExpressionStatement( new MethodCall(new MemberBinding(info, addValueObject), new ExpressionList(new Literal("Kind", SystemTypes.String), new BinaryExpression(new MemberBinding(new This(), kindField), new Literal(contractNodes.ContractFailureKind), NodeType.Box)), NodeType.Call, SystemTypes.Void) )); // info.AddValue("UserMessage", _UserMessage); body.Statements.Add(new ExpressionStatement( new MethodCall(new MemberBinding(info, addValueObject), new ExpressionList(new Literal("UserMessage", SystemTypes.String), new MemberBinding(new This(), userField)), NodeType.Call, SystemTypes.Void) )); // info.AddValue("Condition", _Condition); body.Statements.Add(new ExpressionStatement( new MethodCall(new MemberBinding(info, addValueObject), new ExpressionList(new Literal("Condition", SystemTypes.String), new MemberBinding(new This(), condField)), NodeType.Call, SystemTypes.Void) )); body.Statements.Add(new Return()); contractExceptionType.Members.Add(getObjectData); #endregion } } this.RuntimeContractType.Members.Add(contractExceptionType); return contractExceptionType; }