/// <summary> /// Creates the advice wrapper and adds it to implementation. /// </summary> /// <param name="interfaceMethod">The interface method.</param> /// <param name="implementationType">Type of the implementation.</param> /// <param name="injectAsPrivate">if set to <c>true</c> [inject as private].</param> /// <param name="context">The context.</param> /// <returns></returns> private MethodDef WeaveInterfaceMethod(MethodDef interfaceMethod, TypeDef implementationType, bool injectAsPrivate, WeavingContext context) { var module = implementationType.Module; var typeImporter = new TypeImporter(module); var methodAttributes = MethodAttributes.NewSlot | MethodAttributes.Virtual | (injectAsPrivate ? MethodAttributes.Public : MethodAttributes.Private); var implementationMethodSig = interfaceMethod.MethodSig.Clone(); var implementationMethod = new MethodDefUser(interfaceMethod.Name, /*interfaceMethod.MethodSig */ implementationMethodSig, methodAttributes); for (int parameterIndex = 0; parameterIndex < implementationMethod.Parameters.Count; parameterIndex++) { var parameterType = implementationMethod.Parameters[parameterIndex].Type; if (parameterType != null) { var relocatedParameterType = typeImporter.TryRelocateTypeSig(parameterType) ?? parameterType; implementationMethod.Parameters[parameterIndex].Type = module.Import(relocatedParameterType); } } if (implementationMethod.HasReturnType) { var relocatedReturnType = typeImporter.TryRelocateTypeSig(implementationMethod.ReturnType) ?? implementationMethod.ReturnType; implementationMethod.ReturnType = relocatedReturnType; } implementationMethod.GenericParameters.AddRange(interfaceMethod.GenericParameters); implementationType.Methods.Add(implementationMethod); var interfaceMethodRef = module.Import(interfaceMethod); implementationMethod.Overrides.Add(new MethodOverride(implementationMethod, interfaceMethodRef)); WritePointcutBody(implementationMethod, null, false, context); return(implementationMethod); }
/// <summary> /// Introduces the member. /// </summary> /// <param name="moduleDefinition">The module definition.</param> /// <param name="memberName">Name of the member.</param> /// <param name="memberType">Type of the member.</param> /// <param name="isStatic">if set to <c>true</c> [is static].</param> /// <param name="adviceType">The advice.</param> /// <param name="advisedType">The type definition.</param> /// <param name="markerAttribute">The marker attribute ctor.</param> /// <param name="introducedMemberName">Name of the introduced member.</param> /// <param name="isNotSerialized">if set to <c>true</c> [is not serialized].</param> /// <param name="context">The context.</param> private void IntroduceMember(ModuleDef moduleDefinition, string memberName, ITypeDefOrRef memberType, bool isStatic, ITypeDefOrRef adviceType, TypeDef advisedType, ICustomAttributeType markerAttribute, string introducedMemberName, bool isNotSerialized, WeavingContext context) { if (IsIntroduction(memberType, out var introducedFieldType, out var isShared, context)) { var introducedFieldName = IntroductionRules.GetName(adviceType.Namespace, adviceType.Name, introducedMemberName, memberName, isShared); lock (advisedType.Fields) { if (advisedType.Fields.All(f => f.Name != introducedFieldName)) { var fieldAttributes = (InjectAsPrivate ? FieldAttributes.Private : FieldAttributes.Public) | (isNotSerialized ? FieldAttributes.NotSerialized : 0); if (isStatic) { fieldAttributes |= FieldAttributes.Static; } Logging.WriteDebug("Introduced field type '{0}'", introducedFieldType.FullName); var introducedFieldTypeReference = TypeImporter.Import(moduleDefinition, introducedFieldType.ToTypeSig()); var introducedField = new FieldDefUser(introducedFieldName, new FieldSig(introducedFieldTypeReference), fieldAttributes); introducedField.CustomAttributes.Add(new CustomAttribute(markerAttribute)); advisedType.Fields.Add(introducedField); } } } }
/// <summary> /// Weaves the info advices for the given type. /// </summary> /// <param name="infoAdvisedType">Type of the module.</param> /// <param name="moduleDefinition">The module definition.</param> /// <param name="useWholeAssembly">if set to <c>true</c> [use whole assembly].</param> private void WeaveInfoAdvices(TypeDef infoAdvisedType, ModuleDef moduleDefinition, bool useWholeAssembly) { var invocationType = TypeResolver.Resolve(moduleDefinition, typeof(Invocation)); if (invocationType == null) { return; } var proceedRuntimeInitializersReference = (from m in invocationType.Methods where m.IsStatic && m.Name == nameof(Invocation.ProcessInfoAdvices) let parameters = m.Parameters where parameters.Count == 1 && parameters[0].Type.SafeEquivalent( moduleDefinition.SafeImport(useWholeAssembly ? typeof(Assembly) : typeof(Type)).ToTypeSig()) select m).SingleOrDefault(); if (proceedRuntimeInitializersReference == null) { Logging.WriteWarning("Info advice method not found"); return; } // the cctor needs to be called after all initialization (in case some info advices collect data) infoAdvisedType.Attributes &= ~TypeAttributes.BeforeFieldInit; const string cctorMethodName = ".cctor"; var staticCtor = infoAdvisedType.Methods.SingleOrDefault(m => m.Name == cctorMethodName); var newStaticCtor = staticCtor == null; if (newStaticCtor) { staticCtor = new MethodDefUser(cctorMethodName, MethodSig.CreateStatic(moduleDefinition.CorLibTypes.Void), (InjectAsPrivate ? MethodAttributes.Private : MethodAttributes.Public) | MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName); staticCtor.Body = new CilBody(); infoAdvisedType.Methods.Add(staticCtor); } var instructions = new Instructions(staticCtor.Body.Instructions, staticCtor.Module); var proceedMethod = moduleDefinition.SafeImport(proceedRuntimeInitializersReference); if (useWholeAssembly) { instructions.Emit(OpCodes.Call, moduleDefinition.SafeImport(ReflectionUtility.GetMethodInfo(() => Assembly.GetExecutingAssembly()))); } else { instructions.Emit(OpCodes.Ldtoken, TypeImporter.Import(moduleDefinition, infoAdvisedType.ToTypeSig())); // ReSharper disable once ReturnValueOfPureMethodIsNotUsed var getTypeFromHandleMethodInfo = ReflectionUtility.GetMethodInfo(() => Type.GetTypeFromHandle(new RuntimeTypeHandle())); instructions.Emit(OpCodes.Call, moduleDefinition.SafeImport(getTypeFromHandleMethodInfo)); } instructions.Emit(OpCodes.Call, proceedMethod); // ret is only emitted if the method is new if (newStaticCtor) { instructions.Emit(OpCodes.Ret); } }
public void ImportingMultipleAndDiscovererReturnsNullShouldCauseAnArgumentException() { var containerMock = new Mock<IContainer>(); var typeDiscovererMock = new Mock<ITypeDiscoverer>(); typeDiscovererMock.Setup(t => t.FindMultiple<IMultipleInterface>()).Returns((Type[])null); var typeImporter = new TypeImporter(containerMock.Object, typeDiscovererMock.Object); typeImporter.ImportMany<IMultipleInterface>(); }
public void ImportingMultipleAndDiscovererReturnsNullShouldCauseAnArgumentException() { var containerMock = new Mock <IContainer>(); var typeDiscovererMock = new Mock <ITypeDiscoverer>(); typeDiscovererMock.Setup(t => t.FindMultiple <IMultipleInterface>()).Returns((Type[])null); var typeImporter = new TypeImporter(containerMock.Object, typeDiscovererMock.Object); typeImporter.ImportMany <IMultipleInterface>(); }
public void ImportingMultipleAndThereIsOnlyOneShouldReturnThatInstance() { var containerMock = new Mock<IContainer>(); var typeDiscovererMock = new Mock<ITypeDiscoverer>(); typeDiscovererMock.Setup(t => t.FindMultiple<ISingleInterface>()).Returns(new[] { typeof(SingleClass), }); var typeImporter = new TypeImporter(containerMock.Object, typeDiscovererMock.Object); var instances = typeImporter.ImportMany<ISingleInterface>(); Assert.That(instances.Length, Is.EqualTo(1)); Assert.That(instances[0], Is.InstanceOf<SingleClass>()); }
public void ImportingMultipleShouldReturnAllInstances() { var containerMock = new Mock<IContainer>(); var typeDiscovererMock = new Mock<ITypeDiscoverer>(); typeDiscovererMock.Setup(t => t.FindMultiple<IMultipleInterface>()).Returns(new[] { typeof(FirstMultipleClass), typeof(SecondMultipleClass) }); var typeImporter = new TypeImporter(containerMock.Object, typeDiscovererMock.Object); var instances = typeImporter.ImportMany<IMultipleInterface>(); Assert.That(instances.Length, Is.EqualTo(2)); Assert.That(instances[0], Is.InstanceOf<FirstMultipleClass>()); Assert.That(instances[1], Is.InstanceOf<SecondMultipleClass>()); }
public void ImportingMultipleAndThereIsOnlyOneShouldReturnThatInstance() { var containerMock = new Mock <IContainer>(); var typeDiscovererMock = new Mock <ITypeDiscoverer>(); containerMock.Setup(c => c.Get(typeof(SingleClass))).Returns(new SingleClass()); typeDiscovererMock.Setup(t => t.FindMultiple <ISingleInterface>()).Returns(new[] { typeof(SingleClass), }); var typeImporter = new TypeImporter(containerMock.Object, typeDiscovererMock.Object); var instances = typeImporter.ImportMany <ISingleInterface>(); Assert.That(instances.Length, Is.EqualTo(1)); Assert.That(instances[0], Is.InstanceOf <SingleClass>()); }
public void ImportingMultipleShouldReturnAllInstances() { var containerMock = new Mock <IContainer>(); var typeDiscovererMock = new Mock <ITypeDiscoverer>(); containerMock.Setup(c => c.Get(typeof(FirstMultipleClass))).Returns(new FirstMultipleClass()); containerMock.Setup(c => c.Get(typeof(SecondMultipleClass))).Returns(new SecondMultipleClass()); typeDiscovererMock.Setup(t => t.FindMultiple <IMultipleInterface>()).Returns(new[] { typeof(FirstMultipleClass), typeof(SecondMultipleClass) }); var typeImporter = new TypeImporter(containerMock.Object, typeDiscovererMock.Object); var instances = typeImporter.ImportMany <IMultipleInterface>(); Assert.That(instances.Length, Is.EqualTo(2)); Assert.That(instances[0], Is.InstanceOf <FirstMultipleClass>()); Assert.That(instances[1], Is.InstanceOf <SecondMultipleClass>()); }
/// <summary> /// Weaves the info advices for the given type. /// </summary> /// <param name="infoAdvisedType">Type of the module.</param> /// <param name="moduleDefinition">The module definition.</param> /// <param name="useWholeAssembly">if set to <c>true</c> [use whole assembly].</param> private void WeaveInfoAdvices(TypeDef infoAdvisedType, ModuleDef moduleDefinition, bool useWholeAssembly) { var invocationType = TypeResolver.Resolve(moduleDefinition, typeof(Invocation)); if (invocationType == null) { return; } var proceedRuntimeInitializersReference = (from m in invocationType.Methods where m.IsStatic && m.Name == nameof(Invocation.ProcessInfoAdvices) let parameters = m.Parameters where parameters.Count == 1 && parameters[0].Type.SafeEquivalent( moduleDefinition.SafeImport(useWholeAssembly ? typeof(Assembly) : typeof(Type)).ToTypeSig()) select m).SingleOrDefault(); if (proceedRuntimeInitializersReference == null) { Logging.WriteWarning("Info advice method not found"); return; } var instructions = GetCctorInstructions(infoAdvisedType); var proceedMethod = moduleDefinition.SafeImport(proceedRuntimeInitializersReference); if (useWholeAssembly) { instructions.Emit(OpCodes.Call, moduleDefinition.SafeImport(ReflectionUtility.GetMethodInfo(() => Assembly.GetExecutingAssembly()))); } else { instructions.Emit(OpCodes.Ldtoken, TypeImporter.Import(moduleDefinition, infoAdvisedType.ToTypeSig())); // ReSharper disable once ReturnValueOfPureMethodIsNotUsed var getTypeFromHandleMethodInfo = ReflectionUtility.GetMethodInfo(() => Type.GetTypeFromHandle(new RuntimeTypeHandle())); instructions.Emit(OpCodes.Call, moduleDefinition.SafeImport(getTypeFromHandleMethodInfo)); } instructions.Emit(OpCodes.Call, proceedMethod); }
private void Given_TypeImporter() { var tldser = new TypeLibraryDeserializer(platform.Object, false, typelib); this.typeimporter = new TypeImporter(platform.Object, tldser, new Dictionary <string, Constant>(), typelib); }
public void ShouldPatchGenericsAndArrays() { var testTypes = GetTestTypes().ToArray(); AreEqual(4, testTypes.Length); var mbs = testTypes.SelectMany(GetMemberTypes); var types = mbs.Distinct().OrderBy(t => t.FullName.Length).ToArray(); var dict = new Dictionary <TypeReference, TypeReference>(); var clr = types[0]; var my = types[6]; dict[ToRef(typeof(SuperClass), my)] = ToRef(typeof(decimal), clr); dict[ToRef(typeof(SuperDelegate), my)] = ToRef(typeof(double), clr); dict[ToRef(typeof(SuperStruct), my)] = ToRef(typeof(ulong), clr); dict[ToRef(typeof(SuperWeird), my)] = ToRef(typeof(sbyte), clr); var imp = new TypeImporter(clr); var patcher = Tuple.Create(new TypeSuggestor(dict), new TypePatcher(dict)); AreEqual("System.String", TestSomeType(types[0], patcher, imp).FullName); AreEqual("System.Int32*", TestSomeType(types[1], patcher, imp).FullName); AreEqual("System.UInt32&", TestSomeType(types[2], patcher, imp).FullName); AreEqual("System.UInt32&", TestSomeType(types[3], patcher, imp).FullName); AreEqual("System.Single**", TestSomeType(types[4], patcher, imp).FullName); AreEqual("System.Int16***", TestSomeType(types[5], patcher, imp).FullName); AreEqual("System.Decimal", TestSomeType(types[6], patcher, imp).FullName); AreEqual("System.UInt64", TestSomeType(types[7], patcher, imp).FullName); AreEqual("System.Decimal&", TestSomeType(types[8], patcher, imp).FullName); AreEqual("System.Decimal&", TestSomeType(types[9], patcher, imp).FullName); AreEqual("System.SByte&", TestSomeType(types[10], patcher, imp).FullName); AreEqual("System.SByte&", TestSomeType(types[11], patcher, imp).FullName); AreEqual("System.Double", TestSomeType(types[12], patcher, imp).FullName); AreEqual("System.Double[]", TestSomeType(types[13], patcher, imp).FullName); AreEqual("System.Double[]", TestSomeType(types[14], patcher, imp).FullName); AreEqual("System.Double[][]", TestSomeType(types[15], patcher, imp).FullName); AreEqual("System.Double[][][]", TestSomeType(types[16], patcher, imp).FullName); AreEqual("System.Double[0...,0...]", TestSomeType(types[17], patcher, imp).FullName); AreEqual("System.Double[0...,0...,0...]", TestSomeType(types[18], patcher, imp).FullName); AreEqual("System.Nullable`1<System.UInt64>", TestSomeType(types[19], patcher, imp).FullName); AreEqual("System.Collections.Generic.ISet`1<System.UInt64>", TestSomeType(types[20], patcher, imp).FullName); AreEqual("System.Collections.Generic.IList`1<System.UInt64>", TestSomeType(types[21], patcher, imp).FullName); AreEqual("System.Collections.Generic.IList`1<System.Decimal>&", TestSomeType(types[22], patcher, imp).FullName); AreEqual("System.Collections.Generic.ISet`1<System.Decimal[]>[]&", TestSomeType(types[23], patcher, imp).FullName); AreEqual("System.Collections.Generic.ICollection`1<System.UInt64>", TestSomeType(types[24], patcher, imp).FullName); AreEqual("System.Collections.Generic.IEnumerable`1<System.UInt64>", TestSomeType(types[25], patcher, imp).FullName); AreEqual("System.Action`3<System.String,System.SByte,System.UInt32>", TestSomeType(types[26], patcher, imp).FullName); AreEqual("System.Collections.Generic.IEnumerable`1<System.Double[]>", TestSomeType(types[27], patcher, imp).FullName); AreEqual("System.Tuple`3<System.UInt64,System.String,System.Double>", TestSomeType(types[28], patcher, imp).FullName); AreEqual("System.Collections.Generic.IDictionary`2<System.Double,System.UInt64>", TestSomeType(types[29], patcher, imp).FullName); AreEqual( "System.Collections.Generic.ICollection`1<System.Collections.Generic.IEnumerable`1<System.Double[]>>", TestSomeType(types[30], patcher, imp).FullName); AreEqual( "System.Collections.Generic.IList`1<System.Collections.Generic.ICollection`1<System.Collections.Generic.IEnumerable`1<System.Double[]>>>", TestSomeType(types[31], patcher, imp).FullName); AreEqual( "System.Collections.Generic.ISet`1<System.Collections.Generic.IList`1<System.Collections.Generic.ICollection`1<System.Collections.Generic.IEnumerable`1<System.Double[]>>>>", TestSomeType(types[32], patcher, imp).FullName); AreEqual( "System.Collections.Generic.ISet`1<System.Collections.Generic.IList`1<System.Collections.Generic.ICollection`1<System.Collections.Generic.IEnumerable`1<System.Double[]>[]>>[]>[]", TestSomeType(types[33], patcher, imp).FullName); AreEqual( "System.Collections.Generic.IDictionary`2<System.Collections.Generic.IEnumerable`1<System.Double[]>,System.Collections.Generic.ISet`1<System.Collections.Generic.IList`1<System.Collections.Generic.ICollection`1<System.Tuple`2<System.Double,System.UInt64>>>>>", TestSomeType(types[34], patcher, imp).FullName); AreEqual( "System.Collections.Generic.IDictionary`2<System.Collections.Generic.IEnumerable`1<System.Double>[],System.Collections.Generic.ISet`1<System.Collections.Generic.IList`1<System.Collections.Generic.ICollection`1<System.Tuple`2<System.Double,System.UInt64>>>>[]>", TestSomeType(types[35], patcher, imp).FullName); AreEqual(36, types.Length); }