/// <summary> /// Creates a new <see cref="DualAssemblyResolver"/>. /// </summary> /// <param name="weavingContext">Weaving context to use in assembly resolution.</param> public DualAssemblyResolver(IWeavingContext weavingContext) { Contract.Requires(weavingContext != null); Contract.Ensures(this.WeavingContext != null); this.WeavingContext = weavingContext; }
/// <summary> /// Gets the resolved <see cref="TypeDefinition"/> for a given assembly qualified type name. /// </summary> /// <param name="weavingContext">Context to use when resolving type information.</param> /// <param name="assemblyQualifiedTypeName">Assembly qualified name of the type to resolve.</param> /// <returns>Resolved type.</returns> public static TypeDefinition GetTypeDefinition(this IWeavingContext weavingContext, string assemblyQualifiedTypeName) { Contract.Requires(weavingContext != null); Contract.Requires(assemblyQualifiedTypeName != null); Contract.Ensures(Contract.Result <TypeDefinition>() != null); var nameParts = assemblyQualifiedTypeName.Split(new[] { ',' }, 2, StringSplitOptions.None); if (nameParts.Length != 2) { throw new ArgumentException("Expected type name and assembly name separated by a comma: " + assemblyQualifiedTypeName, "assemblyQualifiedTypeName"); } var assemblyDefinition = weavingContext.AssemblyResolver.Resolve(AssemblyNameReference.Parse(nameParts[1])); if (assemblyDefinition == null) { throw new ArgumentException("Cannot resolve assembly for type: " + assemblyQualifiedTypeName, "assemblyQualifiedTypeName"); } var typeDefinition = assemblyDefinition.MainModule.GetType(nameParts[0]); if (typeDefinition == null) { throw new ArgumentException("Cannot find type within resolved assembly: " + assemblyQualifiedTypeName, "assemblyQualifiedTypeName"); } return(typeDefinition); }
/// <summary> /// Projects a DTO type as a nested type inside of the target type. /// </summary> /// <param name="weavingContext">Weaving context within which the weave is running.</param> /// <param name="target">Target type.</param> /// <param name="weaveAttribute">Attribute that decorated the target type.</param> public void Weave(IWeavingContext weavingContext, TypeDefinition target, CustomAttribute weaveAttribute) { TypeDefinition dtoType = new TypeDefinition( target.Namespace, "Dto", TypeAttributes.Class | TypeAttributes.NestedPublic, target.Module.Import(typeof(object))); target.NestedTypes.Add(dtoType); var dtoMemberAttributeType = target.Module.Import(typeof(DtoMemberAttribute)).Resolve(); foreach (var property in target.Properties) { for (var i = property.CustomAttributes.Count - 1; i >= 0; --i) { var attribute = property.CustomAttributes[i]; if (attribute.AttributeType.Resolve() == dtoMemberAttributeType) { property.CustomAttributes.RemoveAt(i); var field = new FieldDefinition(property.Name, FieldAttributes.Public, property.PropertyType); dtoType.Fields.Add(field); } } } }
/// <summary> /// Contracts for <see cref="IWeave.Initialize"/> /// </summary> /// <param name="weavingContext">Context data for command initialization.</param> /// <param name="weaveConfig">Configuration data for the command. Commands may require particular types for this argument that are subtypes of <see cref="WeaveConfigTypeBase"/></param> public void Initialize(IWeavingContext weavingContext, WeaveConfigTypeBase weaveConfig) { Contract.Requires(weavingContext != null); Contract.Requires(!this.IsInitialized); Contract.Ensures(this.IsInitialized); throw new NotSupportedException(); }
/// <summary> /// Initializes a new instance of the <see cref="MethodWeaver"/> class. /// </summary> /// <param name="classCustomAttributes">Custom attributes of the class of the method.</param> /// <param name="context">Method weaving context.</param> /// <param name="switchHandlerBuilder">Builder of switch handler, used for populating switch initialization of the class.</param> public MethodWeaver( IReadOnlyList <CrossCutterN.Aspect.Metadata.ICustomAttribute> classCustomAttributes, IWeavingContext context, ISwitchHandlerBuilder switchHandlerBuilder) { this.classCustomAttributes = classCustomAttributes ?? throw new ArgumentNullException("classCustomAttributes"); this.context = context ?? throw new ArgumentNullException("context"); this.switchHandlerBuilder = switchHandlerBuilder ?? throw new ArgumentNullException("switchHandlerBuilder"); }
/// <summary> /// Contracts for <see cref="IWeave.Weave"/> /// </summary> /// <param name="weavingContext">Context data for weaving.</param> /// <param name="target">The type to which the weave will be applied/</param> /// <param name="weaveAttribute">Attribute that may contain arguments for the weave invocation.</param> public void Weave(IWeavingContext weavingContext, TypeDefinition target, CustomAttribute weaveAttribute) { Contract.Requires(weavingContext != null); Contract.Requires(target != null); Contract.Requires(weaveAttribute != null); Contract.Requires(this.IsInitialized); throw new NotSupportedException(); }
/// <summary> /// Add switch registering to a class. /// </summary> /// <param name="clazz">The class to register switch.</param> /// <param name="context">The weaving context.</param> /// <param name="switchData">Data of switches.</param> /// <param name="statistics">Weaving statistics.</param> public static void Weave(TypeDefinition clazz, IWeavingContext context, IReadOnlyList <SwitchInitializingData> switchData, IClassWeavingStatisticsBuilder statistics) { #if DEBUG if (clazz == null) { throw new ArgumentNullException("clazz"); } if (context == null) { throw new ArgumentNullException("context"); } if (switchData == null || !switchData.Any()) { throw new ArgumentNullException("switchData"); } if (statistics == null) { throw new ArgumentNullException("statistics"); } #endif var staticConstructor = clazz.Methods.FirstOrDefault(mthd => mthd.IsStaticConstructor()); MethodDefinition method = null; ILProcessor processor = null; if (staticConstructor == null) { method = new MethodDefinition( ".cctor", MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, context.GetTypeReference(typeof(void))); processor = method.Body.GetILProcessor(); method.Body.Instructions.Add(processor.Create(OpCodes.Ret)); clazz.Methods.Add(method); } else { method = staticConstructor; processor = method.Body.GetILProcessor(); } var typeName = clazz.GetFullName(); var instructions = new List <Instruction>(); foreach (var data in switchData) { RegisterSwitch(instructions, processor, context, data, typeName); statistics.AddSwitchWeavingRecord(StatisticsFactory.InitializeSwitchWeavingRecord(typeName, data.Property, data.MethodSignature, data.Aspect, data.Field.Name, data.Value)); } CompleteSwitchRegistration(method, instructions, processor, context, typeName); }
private static void WeaveSwitches( ISwitchHandler switchHandler, TypeDefinition clazz, IWeavingContext context, IClassWeavingStatisticsBuilder statistics) { var switchData = switchHandler.GetData().ToList(); if (switchData.Any()) { SwitchInitializationWeaver.Weave(clazz, context, switchData, statistics); } }
private static void AddAssemblyReference(IWeavingContext context, ModuleDefinition module, IModuleWeavingStatisticsBuilder statistics) { var assemblyReferences = context.AssemblyReferences; if (assemblyReferences != null && assemblyReferences.Any()) { foreach (var reference in assemblyReferences) { if (!module.AssemblyReferences.Any(r => Equals(r.Name, reference.Name))) { module.AssemblyReferences.Add(reference); statistics.AddAssemblyReference(reference.FullName); } } } }
/// <summary> /// Creates a new <see cref="WeavingContextAssemblyResolver"/> /// </summary> /// <param name="weavingContext">Weaving context to pull path data from</param> public WeavingContextAssemblyResolver(IWeavingContext weavingContext) { Contract.Requires(weavingContext != null); Contract.Assert(weavingContext.DefineConstants != null); Contract.Assert(Directory.Exists(weavingContext.ProjectDirectoryPath)); Contract.Assert(Directory.Exists(weavingContext.SolutionDirectoryPath)); // configuration specific path var projectRelativePath = Path.Combine("bin", weavingContext.DefineConstants.Contains("DEBUG") ? "Debug" : "Release"); this.AddSearchDirectory(Path.Combine(weavingContext.ProjectDirectoryPath, projectRelativePath)); // simple bin path, e.g. for asp.net this.AddSearchDirectory(Path.Combine(weavingContext.ProjectDirectoryPath, "bin")); // solution tools path for files created not normally available to the weave target assembly this.AddSearchDirectory(Path.Combine(weavingContext.SolutionDirectoryPath, "Tools")); }
/// <summary> /// Applies the weave to a target type. /// </summary> /// <param name="weavingContext">Context data for weaving.</param> /// <param name="target">The type to which the weave will be applied/</param> /// <param name="weaveAttribute">Attribute that may contain arguments for the weave invocation. This must be of type <see cref="InterfaceMixinAttribute"/>.</param> /// <exception cref="ArgumentException"> /// The <paramref name="weaveAttribute"/> is not of type <see cref="InterfaceMixinAttribute"/>, or it does not /// contain the expected argument values. /// </exception> public void Weave(IWeavingContext weavingContext, TypeDefinition target, CustomAttribute weaveAttribute) { if (weaveAttribute.AttributeType.FullName != weavingContext.GetTypeDefinition(typeof(InterfaceMixinAttribute)).FullName) { throw new ArgumentException("Must be a valid CustomAttribute with AttributeType InterfaceMixAttribute", "weaveAttribute"); } if (weaveAttribute.ConstructorArguments.Count != 1) { throw new ArgumentException("Expected a single constructor argument", "weaveAttribute"); } var mixinInterfaceTypeReference = weaveAttribute.ConstructorArguments[0].Value as TypeReference; if (mixinInterfaceTypeReference == null) { throw new ArgumentException("Expected constructor argument to be a TypeReference", "weaveAttribute"); } var mixinInterfaceType = mixinInterfaceTypeReference.Resolve(); if (!mixinInterfaceType.IsInterface) { weavingContext.LogError(string.Format("Configured mixin interface type is not an interface: [{0}]", mixinInterfaceType.FullName)); // let execution continue...an error will be thrown for this particular weave if invocation is attempted } var matchedMap = this.Config.InterfaceMixinMap.SingleOrDefault( map => map.GetInterfaceType(weavingContext).FullName == mixinInterfaceType.FullName); if (matchedMap == null) { weavingContext.LogWarning("Could not find the a configuration for the requested interface: " + mixinInterfaceType.FullName); return; } new InterfaceMixinWeaver(mixinInterfaceType, matchedMap.GetMixinType(weavingContext), target).Execute(); }
/// <summary> /// Gets the resolved <see cref="TypeDefinition"/> for a given <see cref="Type"/>. /// </summary> /// <param name="weavingContext">Context to use when resolving type information.</param> /// <param name="type">Type to resolve.</param> /// <returns>Resolved type.</returns> public static TypeDefinition GetTypeDefinition(this IWeavingContext weavingContext, Type type) { Contract.Requires(weavingContext != null); Contract.Requires(type != null); Contract.Ensures(Contract.Result <TypeDefinition>() != null); var assemblyDefinition = weavingContext.AssemblyResolver.Resolve(AssemblyNameReference.Parse(type.Assembly.FullName)); if (assemblyDefinition == null) { throw new ArgumentException("Cannot resolve assembly for type: " + type.AssemblyQualifiedName, "type"); } var typeDefinition = assemblyDefinition.MainModule.GetType(type.FullName); if (typeDefinition == null) { throw new ArgumentException("Cannot find type within resolved assembly: " + type.AssemblyQualifiedName, "type"); } return(typeDefinition); }
/// <summary> /// Initializes the command using context and configuration information. /// </summary> /// <param name="weavingContext">Context information for configuration.</param> /// <param name="weaveConfig">Command configuration information. For this command type, the value must be of type <see cref="WeaveConfigTypeBase"/>.</param> /// <exception cref="ArgumentException">The <paramref name="weaveConfig"/> is not of type <see cref="WeaveConfigTypeBase"/></exception> public void Initialize(IWeavingContext weavingContext, WeaveConfigTypeBase weaveConfig) { this.Config = weaveConfig as InterfaceMixinConfigType; this.IsInitialized = true; }
/// <summary> /// Applies the weave to a target type. /// </summary> /// <param name="weavingContext">Context data for weaving.</param> /// <param name="target">The type to which the weave will be applied/</param> /// <param name="weaveAttribute">Attribute that may contain arguments for the weave invocation. This must be of type <see cref="InterfaceMixinAttribute"/>.</param> /// <exception cref="ArgumentException"> /// The <paramref name="weaveAttribute"/> is not of type <see cref="InterfaceMixinAttribute"/>, or it does not /// contain the expected argument values. /// </exception> public void Weave(IWeavingContext weavingContext, TypeDefinition target, CustomAttribute weaveAttribute) { if (weaveAttribute.AttributeType.FullName != weavingContext.GetTypeDefinition(typeof(InterfaceMixinAttribute)).FullName) { throw new ArgumentException("Must be a valid CustomAttribute with AttributeType InterfaceMixAttribute", "weaveAttribute"); } if (weaveAttribute.ConstructorArguments.Count != 1) { throw new ArgumentException("Expected a single constructor argument", "weaveAttribute"); } var mixinInterfaceTypeReference = weaveAttribute.ConstructorArguments[0].Value as TypeReference; if (mixinInterfaceTypeReference == null) { throw new ArgumentException("Expected constructor argument to be a TypeReference", "weaveAttribute"); } var mixinInterfaceType = mixinInterfaceTypeReference.Resolve(); if (!mixinInterfaceType.IsInterface) { weavingContext.LogError(string.Format("Configured mixin interface type is not an interface: [{0}]", mixinInterfaceType.FullName)); // let execution continue...an error will be thrown for this particular weave if invocation is attempted } var matchedMap = this.Config.InterfaceMixinMap.SingleOrDefault( map => map.GetInterfaceType(weavingContext).FullName == mixinInterfaceType.FullName); if(matchedMap == null) { weavingContext.LogWarning("Could not find the a configuration for the requested interface: " + mixinInterfaceType.FullName); return; } new InterfaceMixinWeaver(mixinInterfaceType, matchedMap.GetMixinType(weavingContext), target).Execute(); }
private static void RegisterSwitch(List <Instruction> instructions, ILProcessor processor, IWeavingContext context, SwitchInitializingData data, string typeName) { instructions.Add(processor.Create(OpCodes.Call, context.BaseReference.BackStage.BuilderGetterReference)); instructions.Add(processor.Create(OpCodes.Ldstr, typeName)); instructions.Add(processor.Create(OpCodes.Ldstr, data.Property ?? string.Empty)); instructions.Add(processor.Create(OpCodes.Ldstr, data.MethodSignature)); instructions.Add(processor.Create(OpCodes.Ldstr, data.Aspect)); instructions.Add(processor.Create(data.Value ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0)); instructions.Add(processor.Create(OpCodes.Callvirt, context.BaseReference.Builder.RegisterSwitchMethod)); instructions.Add(processor.Create(OpCodes.Stsfld, data.Field)); }
/// <summary> /// Projects a DTO type as a nested type inside of the target type. /// </summary> /// <param name="weavingContext">Weaving context within which the weave is running.</param> /// <param name="target">Target type.</param> /// <param name="weaveAttribute">Attribute that decorated the target type.</param> public void Weave(IWeavingContext weavingContext, TypeDefinition target, CustomAttribute weaveAttribute) { TypeDefinition dtoType = new TypeDefinition( target.Namespace, "Dto", TypeAttributes.Class | TypeAttributes.NestedPublic, target.Module.Import(typeof(object))); target.NestedTypes.Add(dtoType); var dtoMemberAttributeType = target.Module.Import(typeof (DtoMemberAttribute)).Resolve(); foreach (var property in target.Properties) { for (var i = property.CustomAttributes.Count - 1; i >= 0; --i) { var attribute = property.CustomAttributes[i]; if (attribute.AttributeType.Resolve() == dtoMemberAttributeType) { property.CustomAttributes.RemoveAt(i); var field = new FieldDefinition(property.Name, FieldAttributes.Public, property.PropertyType); dtoType.Fields.Add(field); } } } }
/// <summary> /// Gets the mixin implementation type. /// </summary> /// <param name="weavingContext">Context to use for resolving the type.</param> /// <returns>Resolved mixin definition type.</returns> public TypeDefinition GetMixinType(IWeavingContext weavingContext) { Contract.Requires(weavingContext != null); return(weavingContext.GetTypeDefinition(this.Mixin)); }
/// <summary> /// Gets the mixin implementation type. /// </summary> /// <param name="weavingContext">Context to use for resolving the type.</param> /// <returns>Resolved mixin definition type.</returns> public TypeDefinition GetMixinType(IWeavingContext weavingContext) { Contract.Requires(weavingContext != null); return weavingContext.GetTypeDefinition(this.Mixin); }
/// <summary> /// Initializes the weave. /// </summary> /// <param name="weavingContext">Weaving context that is initializing the weave.</param> /// <param name="weaveConfig">Must be null for this type of weave.</param> public void Initialize(IWeavingContext weavingContext, WeaveConfigTypeBase weaveConfig) { this.IsInitialized = true; }
private static void CompleteSwitchRegistration(MethodDefinition method, List <Instruction> instructions, ILProcessor processor, IWeavingContext context, string clazz) { instructions.Add(processor.Create(OpCodes.Call, context.BaseReference.BackStage.BuilderGetterReference)); instructions.Add(processor.Create(OpCodes.Ldstr, clazz)); instructions.Add(processor.Create(OpCodes.Callvirt, context.BaseReference.Builder.CompleteMethod)); IlUtilities.PersistentInstructions(instructions, processor, method.Body.Instructions.First()); }
/// <summary> /// Gets the mixin definition interface. /// </summary> /// <param name="weavingContext">Context to use for resolving the type.</param> /// <returns>Resolved mixin definition interface type.</returns> public TypeDefinition GetInterfaceType(IWeavingContext weavingContext) { Contract.Requires(weavingContext != null); return(weavingContext.GetTypeDefinition(this.Interface)); }
/// <summary> /// Gets the mixin definition interface. /// </summary> /// <param name="weavingContext">Context to use for resolving the type.</param> /// <returns>Resolved mixin definition interface type.</returns> public TypeDefinition GetInterfaceType(IWeavingContext weavingContext) { Contract.Requires(weavingContext != null); return weavingContext.GetTypeDefinition(this.Interface); }