private List <AdviceArgument> ExtractArguments(MethodDefinition method) { var args = new List <AdviceArgument>(); foreach (var par in method.Parameters) { var argAttr = par.CustomAttributes.FirstOrDefault(ca => ca.AttributeType.IsTypeOf(typeof(Argument))); if (argAttr == null) { _log.LogError(CompilationMessage.From("Unbound arguments are not supported.", method)); continue; } par.CustomAttributes.Remove(argAttr); args.Add(new AdviceArgument { Source = argAttr.GetConstructorValue <Argument.Source>(0), Parameter = par }); } return(args); }
private void CheckInstructionReferencesBroker(Instruction instruction) { if (instruction.OpCode == OpCodes.Ldtoken || instruction.OpCode == OpCodes.Isinst || instruction.OpCode == OpCodes.Castclass || instruction.OpCode == OpCodes.Box || instruction.OpCode == OpCodes.Newarr) { TypeReference type = instruction.Operand as TypeReference; if (type != null) { if (type.BelongsToAssembly(BrokerKeyToken) || IsGenericInstanceArgumentsReferenceBroker(type as GenericInstanceType)) { _log.LogError(CompilationMessage.From("Types from AspectInjector.Broker can't be referenced", instruction)); } } } if (instruction.OpCode == OpCodes.Ldtoken || instruction.OpCode == OpCodes.Call || instruction.OpCode == OpCodes.Callvirt || instruction.OpCode == OpCodes.Newobj) { MethodReference method = instruction.Operand as MethodReference; if (method != null) { if (method.DeclaringType.BelongsToAssembly(BrokerKeyToken) || IsGenericInstanceArgumentsReferenceBroker(method as GenericInstanceMethod)) { _log.LogError(CompilationMessage.From("Types from AspectInjector.Broker can't be referenced", instruction)); } } } }
protected void LoadAdviceArgs(PointCut pc) { foreach (var arg in _effect.Arguments.OrderBy(a => a.Parameter.Index)) { switch (arg.Source) { case Source.Arguments: LoadArgumentsArgument(pc, arg); break; //case Source.Attributes: LoadAttributesArgument(pc, arg); break; case Source.Instance: LoadInstanceArgument(pc, arg); break; case Source.Method: LoadMethodArgument(pc, arg); break; case Source.Name: LoadNameArgument(pc, arg); break; case Source.ReturnType: LoadReturnTypeArgument(pc, arg); break; case Source.ReturnValue: LoadReturnValueArgument(pc, arg); break; case Source.Target: LoadTargetArgument(pc, arg); break; case Source.Type: LoadTypeArgument(pc, arg); break; default: _log.LogError(CompilationMessage.From($"Unknown argument source {arg.Source.ToString()}", _target)); break; } } }
private IReadOnlyCollection <AdviceEffectBase> Extract(MethodDefinition method) { var advices = new List <AdviceEffectBase>(); foreach (var ca in method.CustomAttributes.ToList()) { if (ca.AttributeType.IsTypeOf(typeof(Broker.Advice))) { method.CustomAttributes.Remove(ca); var adviceType = ca.GetConstructorValue <Broker.Advice.Type>(0); var advice = CreateEffect(adviceType); if (advice == null) { _log.LogError(CompilationMessage.From($"Unknown advice type {adviceType.ToString()}", method)); continue; } advice.Method = method; advice.Target = ca.GetConstructorValue <Target>(1); advice.Arguments = ExtractArguments(method); advices.Add(advice); } } return(advices); }
private void CheckMethodBodyReferencesBroker(MethodBody methodBody) { if (methodBody.Variables.Any(v => v.VariableType.BelongsToAssembly(BrokerKeyToken))) { _log.LogError(CompilationMessage.From("Types from AspectInjector.Broker can't be referenced", methodBody.Method)); } methodBody.Instructions.ToList().ForEach(CheckInstructionReferencesBroker); }
public void Weave(Injection injection) { var effect = (AdviceEffectBase)injection.Effect; if (injection.Target is EventDefinition) { var target = (EventDefinition)injection.Target; if (target.AddMethod != null && effect.Target.HasFlag(Target.EventAdd)) { WeaveMethod(target.AddMethod, injection); } if (target.RemoveMethod != null && effect.Target.HasFlag(Target.EventRemove)) { WeaveMethod(target.RemoveMethod, injection); } return; } if (injection.Target is PropertyDefinition) { var target = (PropertyDefinition)injection.Target; if (target.SetMethod != null && effect.Target.HasFlag(Target.Setter)) { WeaveMethod(target.SetMethod, injection); } if (target.GetMethod != null && effect.Target.HasFlag(Target.Getter)) { WeaveMethod(target.GetMethod, injection); } return; } if (injection.Target is MethodDefinition) { var target = (MethodDefinition)injection.Target; if (target.IsConstructor && effect.Target.HasFlag(Target.Constructor)) { WeaveMethod(target, injection); } if (target.IsNormalMethod() && effect.Target.HasFlag(Target.Method)) { WeaveMethod(target, injection); } return; } _log.LogError(CompilationMessage.From($"Unsupported target {injection.Target.GetType().Name}", injection.Target)); }
private void CheckAttributesReferencesBrocker(ICustomAttributeProvider provider) { //todo:: check constructors, firlds, properties foreach (var attr in provider.CustomAttributes) { if (attr.AttributeType.BelongsToAssembly(BrokerKeyToken)) { _log.LogError(CompilationMessage.From("Types from AspectInjector.Broker can't be referenced", provider)); } } }
private void CheckTypeReferencesBroker(TypeDefinition type) { type.Methods.ToList().ForEach(CheckMethodReferencesBroker); if ((type.BaseType != null && (type.BaseType.BelongsToAssembly(BrokerKeyToken) || IsGenericInstanceArgumentsReferenceBroker(type.BaseType as IGenericInstance))) || type.Fields.Any(f => f.FieldType.BelongsToAssembly(BrokerKeyToken) || IsGenericInstanceArgumentsReferenceBroker(f.FieldType as IGenericInstance)) || IsGenericParametersReferenceBroker(type)) { _log.LogError(CompilationMessage.From("Types from AspectInjector.Broker can't be referenced", type)); } type.NestedTypes.ToList().ForEach(CheckTypeReferencesBroker); }
public override bool Validate(AspectDefinition aspect, ILogger log) { if (Method.IsStatic) { log.LogError(CompilationMessage.From($"Advice {Method.FullName} cannot be static.", aspect.Host)); return(false); } if (!Method.IsPublic) { log.LogError(CompilationMessage.From($"Advice {Method.FullName} should be public.", aspect.Host)); return(false); } return(true); }
public override bool Validate(AspectDefinition aspect, ILogger log) { if (!InterfaceType.Resolve().IsInterface) { log.LogError(CompilationMessage.From($"{InterfaceType.FullName} is not an interface.", aspect.Host)); return(false); } if (!aspect.Host.Implements(InterfaceType)) { log.LogError(CompilationMessage.From($"{aspect.Host.FullName} should implement {InterfaceType.FullName}.", aspect.Host)); return(false); } return(true); }
public void ProcessAssembly(AssemblyDefinition assembly) { var aspects = _aspectExtractor.Extract(assembly); foreach (var aspect in aspects) { _cache.Cache(aspect); } var injections = _injectionCollector.Collect(assembly).ToList(); _janitor.Cleanup(assembly); if (_log.IsErrorThrown) { return; } _cache.FlushCache(assembly); foreach (var aspect in aspects) { _assectWeaver.WeaveGlobalAssests(aspect); } foreach (var injector in _effectWeavers.OrderByDescending(i => i.Priority)) { _log.LogInfo($"Executing {injector.GetType().Name}"); foreach (var prioritizedInjections in injections.GroupBy(i => i.Priority).OrderByDescending(a => a.Key).ToList()) { foreach (var injection in prioritizedInjections.OrderByDescending(i => i.Effect.Priority)) { if (injector.CanWeave(injection)) { injector.Weave(injection); injections.Remove(injection); } } } } foreach (var injection in injections) { _log.LogError(CompilationMessage.From($"Couldn't find weaver for {injection.ToString()}", injection.Target)); } }
private void CheckMethodReferencesBroker(MethodDefinition method) { if (method.Parameters.Any(p => p.ParameterType.BelongsToAssembly(BrokerKeyToken) || IsGenericInstanceArgumentsReferenceBroker(p.ParameterType as IGenericInstance)) || method.ReturnType.BelongsToAssembly(BrokerKeyToken) || IsGenericParametersReferenceBroker(method) || IsGenericInstanceArgumentsReferenceBroker(method.ReturnType as IGenericInstance) ) { _log.LogError(CompilationMessage.From("Types from AspectInjector.Broker can't be referenced", method)); } if (method.Body != null) { CheckMethodBodyReferencesBroker(method.Body); } }
private IEnumerable <Injection> ParseInjectionAttribute(ICustomAttributeProvider target, CustomAttribute attr) { var aspectRef = attr.GetConstructorValue <TypeReference>(0); var aspect = _cache.ReadAspect(aspectRef.Resolve()); if (aspect == null) { _log.LogError(CompilationMessage.From($"Type {aspectRef.FullName} should be an aspect class.", target)); return(Enumerable.Empty <Injection>()); } var priority = attr.GetPropertyValue <Broker.Inject, ushort>(i => i.Priority); // var childFilter = attr.GetPropertyValue<Broker.Inject, InjectionChildFilter>(i => i.Filter); var injections = FindApplicableMembers(target, aspect, priority /*, childFilter*/); return(injections); }
public int Execute(IReadOnlyList <string> args) { if (args.Count == 0) { ShowHelp(); return(-1); } var filename = args[0]; var optimize = args[1] == "-o"; var refsStart = optimize ? 2 : 1; var references = new ArraySegment <string>(args.ToArray(), refsStart, args.Count - refsStart); if (!File.Exists(filename)) { ShowHelp($"File {filename} does not exist."); return(1); } var log = new ConsoleLogger(); var processor = CreateProcessor(log); var resolver = new KnownReferencesAssemblyResolver(); resolver.AddSearchDirectory(Path.GetDirectoryName(filename)); references.ToList().ForEach(resolver.AddReference); try { processor.Process(filename, resolver, optimize); } catch (Exception e) { log.LogError(CompilationMessage.From(e.ToString())); } return(log.IsErrorThrown ? 1 : 0); }
public override bool Validate(AspectDefinition aspect, ILogger log) { if (Method.IsStatic) { log.LogError(CompilationMessage.From($"Advice {Method.FullName} cannot be static.", aspect.Host)); return(false); } if (!Method.IsPublic) { log.LogError(CompilationMessage.From($"Advice {Method.FullName} should be public.", aspect.Host)); return(false); } if (Method.ReturnType != Method.Module.TypeSystem.Object) { log.LogError(CompilationMessage.From($"Around advice {Method.FullName} should return an object. Could return null.", aspect.Host)); return(false); } return(true); }
public AspectDefinition ReadAspect(TypeDefinition type) { var effects = ExtractEffects(type).ToList(); var aspect = ExtractAspectAttribute(type); if (aspect != null) { return new AspectDefinition { Host = type, Scope = aspect.GetConstructorValue <Aspect.Scope>(0), Factory = aspect.GetPropertyValue <Aspect>(au => au.Factory) as TypeReference, Effects = effects } } ; if (effects.Any()) { _log.LogError(CompilationMessage.From($"Type {type.FullName} has effects, but is not marked as an aspect. Concider using [Aspect] attribute.", type)); } return(null); }
public void ProcessAssembly(AssemblyDefinition assembly, bool optimize) { var aspects = _aspectExtractor.Extract(assembly); foreach (var aspect in aspects) { _cache.Cache(aspect); } var injections = _injectionCollector.Collect(assembly).ToList(); injections = ExcludeAspectInjections(injections, aspects); _janitor.Cleanup(assembly); if (_log.IsErrorThrown) { return; } _cache.FlushCache(assembly); _log.LogInfo($"Stored {aspects.Count} aspects"); foreach (var aspect in aspects) { _aspectWeaver.WeaveGlobalAssests(aspect); } _log.LogInfo($"Found {injections.Count} injections"); foreach (var injector in _effectWeavers.OrderByDescending(i => i.Priority)) { _log.LogInfo($"Executing {injector.GetType().Name}"); foreach (var prioritizedInjections in injections.GroupBy(i => i.Priority).OrderByDescending(a => a.Key).ToList()) { foreach (var injection in prioritizedInjections.OrderByDescending(i => i.Effect.Priority)) { if (injector.CanWeave(injection)) { injector.Weave(injection); injections.Remove(injection); } } } } foreach (var injection in injections) { _log.LogError(CompilationMessage.From($"Couldn't find weaver for {injection.ToString()}", injection.Target)); } if (optimize) { _log.LogInfo($"Cleanup and optimize."); } else { _log.LogInfo($"Cleanup."); } foreach (var module in assembly.Modules) { if (optimize) { EditorFactory.Optimize(module); } EditorFactory.CleanUp(module); } }
protected virtual void LoadReturnValueArgument(PointCut pc, AdviceArgument parameter) { _log.LogWarning(CompilationMessage.From($"Advice {_effect.Type.ToString()} does not support {parameter.Source.ToString()} argument and will always return null", _effect.Method)); pc.Null(); }
private void ProcessAssembly(AssemblyDefinition assembly) { var aspects = _aspectExtractor.Extract(assembly); foreach (var aspect in aspects) { _cache.Cache(aspect); } var injections = _injectionCollector.Collect(assembly).ToList(); injections = ExcludeAspectInjections(injections, aspects); _janitor.Cleanup(assembly); if (_log.IsErrorThrown) { return; } _cache.FlushCache(assembly); foreach (var aspect in aspects) { _aspectWeaver.WeaveGlobalAssests(aspect); } foreach (var injector in _effectWeavers.OrderByDescending(i => i.Priority)) { _log.LogInfo($"Executing {injector.GetType().Name}"); foreach (var prioritizedInjections in injections.GroupBy(i => i.Priority).OrderByDescending(a => a.Key).ToList()) { foreach (var injection in prioritizedInjections.OrderByDescending(i => i.Effect.Priority)) { if (injector.CanWeave(injection)) { injector.Weave(injection); injections.Remove(injection); } } } } foreach (var injection in injections) { _log.LogError(CompilationMessage.From($"Couldn't find weaver for {injection.ToString()}", injection.Target)); } var isInRelease = false; var debugAttr = assembly.CustomAttributes.FirstOrDefault(a => a.AttributeType.IsTypeOf(typeof(DebuggableAttribute))); if (!debugAttr.GetConstructorValue <DebuggableAttribute.DebuggingModes>(0).HasFlag(DebuggableAttribute.DebuggingModes.DisableOptimizations)) { isInRelease = true; } foreach (var module in assembly.Modules) { if (isInRelease) { EditorFactory.Optimize(module); } EditorFactory.CleanUp(module); } }