/// <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="markerAttributeCtor">The marker attribute ctor.</param> private void IntroduceMember(ModuleDefinition moduleDefinition, string memberName, TypeReference memberType, bool isStatic, TypeReference adviceType, TypeDefinition advisedType, MethodReference markerAttributeCtor) { TypeReference introducedFieldType; if (IsIntroduction(memberType, out introducedFieldType)) { var introducedFieldName = IntroductionRules.GetName(adviceType.Namespace, adviceType.Name, memberName); lock (advisedType.Fields) { if (advisedType.Fields.All(f => f.Name != introducedFieldName)) { var fieldAttributes = (InjectAsPrivate ? FieldAttributes.Private : FieldAttributes.Public) | FieldAttributes.NotSerialized; if (isStatic) fieldAttributes |= FieldAttributes.Static; Logger.WriteDebug("Introduced field type '{0}'", introducedFieldType.FullName); var introducedFieldTypeReference = moduleDefinition.SafeImport(introducedFieldType); var introducedField = new FieldDefinition(introducedFieldName, fieldAttributes, introducedFieldTypeReference); introducedField.CustomAttributes.Add(new CustomAttribute(markerAttributeCtor)); advisedType.Fields.Add(introducedField); } } } }
/// <summary> /// Gets the target framework. /// </summary> /// <param name="moduleDefinition">The module definition.</param> /// <returns></returns> /// <exception cref="System.ArgumentOutOfRangeException"></exception> private static TargetFramework GetTargetFramework(ModuleDefinition moduleDefinition) { var targetFrameworkAttributeType = moduleDefinition.SafeImport(typeof(TargetFrameworkAttribute)); var targetFrameworkAttribute = moduleDefinition.Assembly.CustomAttributes.SingleOrDefault(a => a.AttributeType.SafeEquivalent(targetFrameworkAttributeType)); if (targetFrameworkAttribute == null) { switch (moduleDefinition.Runtime) { case TargetRuntime.Net_1_0: return new TargetFramework(new Version(1, 0)); case TargetRuntime.Net_1_1: return new TargetFramework(new Version(1, 1)); case TargetRuntime.Net_2_0: return new TargetFramework(new Version(2, 0)); case TargetRuntime.Net_4_0: return new TargetFramework(new Version(4, 0)); default: throw new ArgumentOutOfRangeException(); } } return new TargetFramework((string)targetFrameworkAttribute.ConstructorArguments[0].Value); }
/// <summary> /// Weaves the interface. /// What we do here is: /// - creating a class (wich is named after the interface name) /// - this class implements all interface members /// - all members invoke Invocation.ProcessInterfaceMethod /// </summary> /// <param name="moduleDefinition">The module definition.</param> /// <param name="interfaceType">Type of the interface.</param> private void WeaveInterface(ModuleDefinition moduleDefinition, TypeReference interfaceType) { Logger.WriteDebug("Weaving interface '{0}'", interfaceType.FullName); TypeDefinition implementationType; TypeDefinition advisedInterfaceType; TypeDefinition interfaceTypeDefinition; lock (moduleDefinition) { // ensure we're creating the interface only once var implementationTypeName = GetImplementationTypeName(interfaceType.Name); var implementationTypeNamespace = interfaceType.Namespace; if (moduleDefinition.GetTypes().Any(t => t.Namespace == implementationTypeNamespace && t.Name == implementationTypeName)) return; // now, create the implementation type interfaceTypeDefinition = interfaceType.Resolve(); var typeAttributes = (InjectAsPrivate ? TypeAttributes.NotPublic : TypeAttributes.Public) | TypeAttributes.Class | TypeAttributes.BeforeFieldInit; advisedInterfaceType = TypeResolver.Resolve(moduleDefinition, Binding.AdvisedInterfaceTypeName, true); var advisedInterfaceTypeReference = moduleDefinition.SafeImport(advisedInterfaceType); implementationType = new TypeDefinition(implementationTypeNamespace, implementationTypeName, typeAttributes, advisedInterfaceTypeReference); lock (moduleDefinition) moduleDefinition.Types.Add(implementationType); } implementationType.Interfaces.Add(interfaceType); // create empty .ctor. This .NET mofo wants it! var baseEmptyConstructor = moduleDefinition.SafeImport(advisedInterfaceType.Resolve().GetConstructors().Single()); const MethodAttributes ctorAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName; var method = new MethodDefinition(".ctor", ctorAttributes, moduleDefinition.TypeSystem.Void); method.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0)); method.Body.Instructions.Add(Instruction.Create(OpCodes.Call, baseEmptyConstructor)); method.Body.Instructions.Add(Instruction.Create(OpCodes.Ret)); implementationType.Methods.Add(method); // create implementation methods foreach (var interfaceMethod in interfaceTypeDefinition.GetMethods().Where(m => !m.IsSpecialName)) WeaveInterfaceMethod(interfaceMethod, implementationType, true); // create implementation properties foreach (var interfaceProperty in interfaceTypeDefinition.Properties) { var implementationProperty = new PropertyDefinition(interfaceProperty.Name, PropertyAttributes.None, interfaceProperty.PropertyType); implementationType.Properties.Add(implementationProperty); if (interfaceProperty.GetMethod != null) implementationProperty.GetMethod = WeaveInterfaceMethod(interfaceProperty.GetMethod, implementationType, InjectAsPrivate); if (interfaceProperty.SetMethod != null) implementationProperty.SetMethod = WeaveInterfaceMethod(interfaceProperty.SetMethod, implementationType, InjectAsPrivate); } // create implementation events foreach (var interfaceEvent in interfaceTypeDefinition.Events) { var implementationEvent = new EventDefinition(interfaceEvent.Name, EventAttributes.None, moduleDefinition.SafeImport(interfaceEvent.EventType)); implementationType.Events.Add(implementationEvent); if (interfaceEvent.AddMethod != null) implementationEvent.AddMethod = WeaveInterfaceMethod(interfaceEvent.AddMethod, implementationType, InjectAsPrivate); if (interfaceEvent.RemoveMethod != null) implementationEvent.RemoveMethod = WeaveInterfaceMethod(interfaceEvent.RemoveMethod, implementationType, InjectAsPrivate); } }
/// <summary> /// Weaves the introductions. /// Introduces members as requested by aspects /// </summary> /// <param name="method">The method.</param> /// <param name="adviceInterface">The advice interface.</param> /// <param name="moduleDefinition">The module definition.</param> private void WeaveIntroductions(MethodDefinition method, TypeDefinition adviceInterface, ModuleDefinition moduleDefinition) { var typeDefinition = method.DeclaringType; var advices = GetAllMarkers(new MethodReflectionNode(method), adviceInterface); var markerAttributeCtor = moduleDefinition.SafeImport(TypeResolver.Resolve(moduleDefinition, Binding.IntroducedFieldAttributeName, true) .GetConstructors().Single()); foreach (var advice in advices) { var adviceDefinition = advice.Resolve(); foreach (var field in adviceDefinition.Fields.Where(f => f.IsPublic)) IntroduceMember(method.Module, field.Name, field.FieldType, field.IsStatic, advice, typeDefinition, markerAttributeCtor); foreach (var property in adviceDefinition.Properties.Where(p => p.HasAnyPublic())) IntroduceMember(method.Module, property.Name, property.PropertyType, !property.HasThis, advice, typeDefinition, markerAttributeCtor); } }
/// <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(TypeDefinition infoAdvisedType, ModuleDefinition moduleDefinition, bool useWholeAssembly) { var invocationType = TypeResolver.Resolve(moduleDefinition, Binding.InvocationTypeName, true); if (invocationType == null) return; var proceedRuntimeInitializersReference = (from m in invocationType.GetMethods() where m.IsStatic && m.Name == Binding.InvocationProcessInfoAdvicesMethodName let parameters = m.Parameters where parameters.Count == 1 && parameters[0].ParameterType.SafeEquivalent( moduleDefinition.SafeImport(useWholeAssembly ? typeof(Assembly) : typeof(Type))) select m).SingleOrDefault(); if (proceedRuntimeInitializersReference == null) { Logger.WriteWarning("Info advice method not found"); return; } const string cctorMethodName = ".cctor"; var staticCtor = infoAdvisedType.Methods.SingleOrDefault(m => m.Name == cctorMethodName); if (staticCtor == null) { staticCtor = new MethodDefinition(cctorMethodName, (InjectAsPrivate ? MethodAttributes.Private : MethodAttributes.Public) | MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, moduleDefinition.SafeImport(typeof(void))); 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, moduleDefinition.SafeImport(infoAdvisedType)); // ReSharper disable once ReturnValueOfPureMethodIsNotUsed var getTypeFromHandleMethodInfo = ReflectionUtility.GetMethodInfo(() => Type.GetTypeFromHandle(new RuntimeTypeHandle())); instructions.Emit(OpCodes.Call, moduleDefinition.SafeImport(getTypeFromHandleMethodInfo)); } instructions.Emit(OpCodes.Call, proceedMethod); instructions.Emit(OpCodes.Ret); }