Coder Social home page Coder Social logo

pamidur / aspect-injector Goto Github PK

View Code? Open in Web Editor NEW
732.0 732.0 107.0 13.48 MB

AOP framework for .NET (c#, vb, etc)

License: Apache License 2.0

C# 99.05% PowerShell 0.71% Visual Basic .NET 0.25%
advice aop aop-framework aot aspect aspects attribute attributes blazor c-sharp compile-time dotnet dotnet-core injection inpc mixin mixins postsharp wrap wrapper

aspect-injector's Introduction

image

I have never asked for any donations, but today, I ask you, please, consider donating Ukrainian Army.

You can find official ways to do it here or you can donate to the biggest charity organization here

People need to be alive to create open source projects!





Aspect Injector

Aspect Injector is an attribute-based framework for creating and injecting aspects into your .net assemblies.

Project Status

Nuget Nuget Pre Nuget

GitHub (Pre-)Release Date GitHub last commit

Application Status Samples Status

Download

> dotnet add package AspectInjector

Features

  • Compile-time injection - works with Blazor and AOT
  • Injecting Before, After and Around (wrap) Methods, Constructors, Properties and Events
  • Injecting Interface implementations
  • Supports any project that can reference netstandard2.0 libraries, see here
  • Debugging support
  • Roslyn analyzers for your convenience (only c# currently)
  • Can work DI/IoC frameworks #166

Check out samples and docs

Requirements

  • (semi-optional) Nuget 5.0+ for transient build feature. All modern versions of VS and dotnetsdk have it. (If you still use project.json for some reason - make sure you add AspectInjector to all projects in the solution)
  • (optional) For analyzers to work in VSCode, don't forget to enable "omnisharp.enableRoslynAnalyzers": true

Known Issues / Limitations

  • Unsafe methods are not supported and are silently ignored.

Simple advice

Create an aspect with simple advice:

[Aspect(Scope.Global)]
[Injection(typeof(LogCall))]
public class LogCall : Attribute
{
    [Advice(Kind.Before)] // you can have also After (async-aware), and Around(Wrap/Instead) kinds
    public void LogEnter([Argument(Source.Name)] string name)
    {
        Console.WriteLine($"Calling '{name}' method...");   //you can debug it	
    }
}

Use it:

[LogCall]
public void Calculate() 
{ 
    Console.WriteLine("Calculated");
}

Calculate();

Result:

$ dotnet run
Calling 'Calculate' method...
Calculated

Simple mixin

Create an aspect with mixin:

public interface IInitializable
{
    void Init();
}

[Aspect(Scope.PerInstance)]
[Injection(typeof(Initializable))]
[Mixin(typeof(IInitializable))]
public class Initializable : IInitializable, Attribute
{
    public void Init()
    {
        Console.WriteLine("Initialized!");
    }
}

Use it:

[Initializable]
public class Target
{ 
}

var target = new Target() as IInitializable;
target.Init();

Result:

$ dotnet run
Initialized!

aspect-injector's People

Contributors

jerviscui avatar kondr1 avatar maciejwanat avatar om2804 avatar pamidur avatar pvoshell avatar stefh avatar wssmith avatar yuriyivon avatar zhipu123 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aspect-injector's Issues

Visual Studio 2015 - AspectInjector - PdbDebugException issue

We are using AspectInjector Version 0.9.41 in our portal class library (Targets .NET Framework 4.5+ Windows 8 + Windows Phone 8.1 + Windows Phone Silverlight 8) and Windows phone 8.0 Silverlight app.

Visual Studio 2013 compiles the Solution without any build error.

Visual Studio 2015 compiles the Solution with following errors with Stacktrace

Error PdbDebugException: Unknown custom metadata item kind: 7 at Microsoft.Cci.Pdb.PdbFunction.ReadCustomMetadata(BitAccess bits) at Microsoft.Cci.Pdb.PdbFunction..ctor(ManProcSym proc, BitAccess bits) at Microsoft.Cci.Pdb.PdbFunction.LoadManagedFunctions(BitAccess bits, UInt32 limit, Boolean readStrings) at Microsoft.Cci.Pdb.PdbFile.LoadFuncsFromDbiModule(BitAccess bits, DbiModuleInfo info, IntHashTable names, ArrayList funcList, Boolean readStrings, MsfDirectory dir, Dictionary2 nameIndex, PdbReader reader) at Microsoft.Cci.Pdb.PdbFile.LoadFunctions(Stream read, Dictionary2& tokenToSourceMapping, String& sourceServerData) at Mono.Cecil.Pdb.PdbReader.PopulateFunctions() at Mono.Cecil.Pdb.PdbReader.ProcessDebugHeader(ImageDebugDirectory directory, Byte[] header) at Mono.Cecil.ModuleDefinition.ProcessDebugHeader() at Mono.Cecil.ModuleDefinition.ReadSymbols(ISymbolReader reader) at Mono.Cecil.ModuleReader.ReadSymbols(ModuleDefinition module, ReaderParameters parameters) at Mono.Cecil.ModuleReader.CreateModuleFrom(Image image, ReaderParameters parameters) at Mono.Cecil.ModuleDefinition.ReadModule(Stream stream, ReaderParameters parameters) at Mono.Cecil.ModuleDefinition.ReadModule(String fileName, ReaderParameters parameters) at AspectInjector.BuildTask.AspectInjectorBuildTask.Execute()

Error PdbDebugException: Unknown custom metadata item kind: 6 at Microsoft.Cci.Pdb.PdbFunction.ReadCustomMetadata(BitAccess bits) at Microsoft.Cci.Pdb.PdbFunction..ctor(ManProcSym proc, BitAccess bits) at Microsoft.Cci.Pdb.PdbFunction.LoadManagedFunctions(BitAccess bits, UInt32 limit, Boolean readStrings) at Microsoft.Cci.Pdb.PdbFile.LoadFuncsFromDbiModule(BitAccess bits, DbiModuleInfo info, IntHashTable names, ArrayList funcList, Boolean readStrings, MsfDirectory dir, Dictionary2 nameIndex, PdbReader reader) at Microsoft.Cci.Pdb.PdbFile.LoadFunctions(Stream read, Dictionary2& tokenToSourceMapping, String& sourceServerData) at Mono.Cecil.Pdb.PdbReader.PopulateFunctions() at Mono.Cecil.Pdb.PdbReader.ProcessDebugHeader(ImageDebugDirectory directory, Byte[] header) at Mono.Cecil.ModuleDefinition.ProcessDebugHeader() at Mono.Cecil.ModuleDefinition.ReadSymbols(ISymbolReader reader) at Mono.Cecil.ModuleReader.ReadSymbols(ModuleDefinition module, ReaderParameters parameters) at Mono.Cecil.ModuleReader.CreateModuleFrom(Image image, ReaderParameters parameters) at Mono.Cecil.ModuleDefinition.ReadModule(Stream stream, ReaderParameters parameters) at Mono.Cecil.ModuleDefinition.ReadModule(String fileName, ReaderParameters parameters) at AspectInjector.BuildTask.AspectInjectorBuildTask.Execute()

Please fix this issue.

Could not execute the method because either the method itself or the containing type is not fully instantiated.

Hi, i found this issue when working with static method in a Generic function.
This is my class model:


  class Program
    {
        static void Main(string[] args)
        {
            SampleClass<int>.Method1(222);
            SampleClass<int>.Method2();

            Console.ReadLine();
      
         
        }
        
    }
  [Aspect(typeof(MyLogging))]
    public class SampleClass<T>
    {
        public static void Method1(int x)
        {
            Console.WriteLine("x");
            //...
        }

        public static int Method2()
        {
            Console.WriteLine("x");

            return 1;
        }
    }

New Injection Methods (base classes, interfaces, vistrual methods)

This is a great project. Is simple but powerful. There is a feature that maybe you should consider. If I define a class with an abstract method decorated with an Aspect attribute, I'd like to all implementations of that method should have the aspect injected inside his code. I tested this with 1.0.0-beta3.

[BUG] There is NullReferenceException if use Aspect with generic types

Steps to reproduce:

  1. Create portable library .dll and TraceAspect within
  2. Create 4.5 framework .dll with generic class TestClass
  3. Use [Aspect(typeof(TraceAspect))] for TestClass

Error 1 NullReferenceException: Object reference not set to an instance of an object.
at AspectInjector.BuildTask.Extensions.TypeExtensions.IsTypeOf(TypeReference typeReference1, TypeReference typeReference2)
at AspectInjector.BuildTask.Extensions.TypeExtensions.IsTypeOf(TypeReference typeReference, Type type)
at AspectInjector.BuildTask.Contexts.TargetMethodContext.SetupSingleReturnPoint(Instruction suggestedSingleReturnPoint)
at AspectInjector.BuildTask.Contexts.TargetMethodContext.SetupReturnPoints()
at AspectInjector.BuildTask.Contexts.TargetMethodContext..ctor(MethodDefinition targetMethod)
at AspectInjector.BuildTask.Contexts.MethodContextFactory.GetOrCreateContext(MethodDefinition md)
at AspectInjector.BuildTask.Processors.ModuleProcessors.InjectionProcessor.ProcessAspectAttributes(MethodDefinition targetMethod, String targetName, IEnumerable`1 aspectAttributes)
at AspectInjector.BuildTask.Processors.ModuleProcessors.InjectionProcessor.ProcessModule(ModuleDefinition module)
at AspectInjector.BuildTask.Processors.AssemblyProcessor.Process(AssemblyDefinition assembly)
at AspectInjector.BuildTask.AspectInjectorBuildTask.Execute()
ITWORK.Solutions.FishingForecast.WebServices

Add ordering possibilities

The fact is compiler doesn't necessary have to put attributes into an assembly in order they are stated in the code.
The issue is there. Especially in release configuration.

We might introduce Order parameter into AspectAttribute. Don't know what to do with custom attributes though. What is your opinion?

[BUG] AdviceArgumentSource.Method contains an invalid value in InjectionPoints.Around

Source:

class Program
{
    static void Main(string[] args)
    {
        Test();
    }

    [Aspect(typeof(LoggingAspect))]
    static void Test()
    {
        Console.WriteLine("Processing");
    }
}

class LoggingAspect
{
    [Advice(InjectionPoints.Around, InjectionTargets.Method)]
    public Object Log(
        [AdviceArgument(AdviceArgumentSource.Name)] String name,
        [AdviceArgument(AdviceArgumentSource.Method)] MethodBase method,
        [AdviceArgument(AdviceArgumentSource.Arguments)] Object[] args,
        [AdviceArgument(AdviceArgumentSource.Target)] Func<Object[], Object> target)
    {
        if (name != method.Name) Console.WriteLine("{0} != {1}", name, method.Name);
        return target(args);
    }
}

Result:

2016-02-08_1500

Compiled source:

internal class Program
{
    private static LoggingAspect __a$_LoggingAspect;
    private static void Main(string[] args)
    {
        Program.Test();
    }
    private static void Test()
    {
        object[] array = new object[0];
        object obj = Program.__a$w0_Test(array);
    }
    private static void __a$_initializeTypeAspects()
    {
        if (Program.__a$_LoggingAspect == null)
        {
            Program.__a$_LoggingAspect = new LoggingAspect();
        }
    }
    static Program()
    {
        // Note: this type is marked as 'beforefieldinit'.
        Program.__a$_initializeTypeAspects();
    }
    private static void __a$o_Test()
    {
        Console.WriteLine("Processing");
    }
    [DebuggerHidden, CompilerGenerated]
    private static object __a$u_Test(object[] array)
    {
        Program.__a$o_Test();
        return null;
    }
    [DebuggerHidden, CompilerGenerated]
    private static object __a$w0_Test(object[] args)
    {
        return Program.__a$_LoggingAspect.Log("Test", (MethodBase)MethodBase.GetMethodFromHandle(methodof(Program.__a$o_Test()).MethodHandle), args, delegate
        {
            Program.__a$o_Test();
            return null;
        });
    }
}

Multiply CustomAspects on one target

First of all - thank you for the library - it is great alternative for PostSharp.
But I have one question about the implementation of the CustomAspect's feature - is it possible to use several attributes on the target?

For example:

TestAspectAttribute source code:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Event, AllowMultiple = true)]
[CustomAspectDefinition(typeof(FacSetupAspectImplementation))]
public class TestAspectAttribute : Attribute
{
    public string Header { get; private set; }
    public string Value { get; set; }
    public int data = 42;

    public TestAspectAttribute(string header)
    {
        Header = header;
    }
}

TestAspectImplementation

public class TestAspectImplementation
{
    [Advice(InjectionPoints.After, InjectionTargets.Method)]
        public void AfterMethod([AdviceArgument(AdviceArgumentSource.RoutableData)] object data)
        {
            var a = (data as TestAspectAttribute);

            Checker.Passed = a.Header == "TestHeader" && a.Value == "ololo" && a.data == 43;
        }
}

TestClass

public class TestClass
{
    [TestAspect("TestHeader", Value = "ololo", data = 43)] // first
    [TestAspect("Another", Value = "Hehe", data = 0)] //second
    public void Do()
    {
        Console.Write("");
    }
}

And in the decompiled sources we've got:

public class TestClass
{
    private FacSetupAspectImplementation __a$_FacSetupAspectImplementation;

    [TestAspect("Another", Value = "Hehe", data = 0), TestAspect("TestHeader", Value = "ololo", data = 43)]
    public void Do()
    {
        this.__a$_FacSetupAspectImplementation.AfterMethod(this, new TestAspectAttribute("Another")
        {
            Value = "Hehe",
            data = 0
        });
        Console.Write("");
    }

    public TestClass()
    {
        this.__a$_initializeInstanceAspects();
    }

    private void __a$_initializeInstanceAspects()
    {
        if (this.__a$_FacSetupAspectImplementation == null)
        {
            this.__a$_FacSetupAspectImplementation = new FacSetupAspectImplementation();
        }
    }
}

Could you please say if it is possible to fix?

[BUG] There is ArgumentOutOfRangeException if Release compilation plan is selected

In Debug mode code builds just fine and work.
See class which causes exception below:

Error 202 ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: target
at Mono.Cecil.Cil.ILProcessor.InsertBefore(Instruction target, Instruction instruction)
at AspectInjector.BuildTask.Contexts.TargetMethodContext.SetupSingleReturnPoint(Instruction suggestedSingleReturnPoint)
at AspectInjector.BuildTask.Contexts.TargetMethodContext.SetupReturnPoints()
at AspectInjector.BuildTask.Contexts.TargetMethodContext..ctor(MethodDefinition targetMethod)
at AspectInjector.BuildTask.Contexts.MethodContextFactory.GetOrCreateContext(MethodDefinition md)
at AspectInjector.BuildTask.Processors.ModuleProcessors.InjectionProcessor.ProcessAspectAttributes(MethodDefinition targetMethod, String targetName, IEnumerable`1 aspectAttributes)
at AspectInjector.BuildTask.Processors.ModuleProcessors.InjectionProcessor.ProcessModule(ModuleDefinition module)
at AspectInjector.BuildTask.Processors.AssemblyProcessor.Process(AssemblyDefinition assembly)
at AspectInjector.BuildTask.AspectInjectorBuildTask.Execute()
OR.Data.Core

Target class
[Export(typeof(IPatientsService))]
[Aspect(typeof(TraceAspect))]
public class PatientsService : IPatientsService
{
private readonly IDiagnosisRepository _diagnosisRepository;
private readonly IDispensaryMarkRepository _dispensaryMarkRepository;
private readonly IPassportRepository _passportRepository;
private readonly IClinicalGroupsRepository _clinicalGroupsRepository;
private readonly ISendCallRepository _sendCallRepository;

    [ImportingConstructor]
    public PatientsService(IPassportRepository passportRepository,
        IDiagnosisRepository diagRepository,
        IDispensaryMarkRepository dispensaryMarkRepository,
        IClinicalGroupsRepository clinicalGroupsRepository,
        ISendCallRepository sendCallRepository)
    {
        _diagnosisRepository = diagRepository;
        _dispensaryMarkRepository = dispensaryMarkRepository;
        _passportRepository = passportRepository;
        _clinicalGroupsRepository = clinicalGroupsRepository;
        _sendCallRepository = sendCallRepository;
    }

    public IDiagnosis CreateNewDiagnosis()
    {
        return _diagnosisRepository.Create();
    }

    public IPatient GetById(string id)
    {
        var passport = _passportRepository.GetById(id);

        if (passport == null)
        {
            return null;
        }

        var diagnoses = _diagnosisRepository.GetAllForPatient(id);
        var clinicalGroups = _clinicalGroupsRepository.GetAllForPatient(id);

        var patient = new Patient(passport, diagnoses, clinicalGroups);
        return patient;
    }

    public void DeletePatient(IPatient patient)
    {
        var passport = _passportRepository.GetById(patient.Id);
        if (passport != null)
        {
            //diagnoses delete by dbTrigger
            _passportRepository.DeleteByKey(passport.Id);
        }
    }

    public string GeneratePatientId()
    {
        return _passportRepository.GeneratePatientId();
    }

    public IPassport GetPassport(IPatient patient)
    {
        return _passportRepository.GetById(patient.Id);
    }

    public void AddPatient(IPatient patient)
    {
        if (patient.Passport == null)
        {
            throw new ArgumentException("Can't to add patient without passport");
        }
        _passportRepository.Create(patient.Passport);
    }

    public void UpdatePatient(IPatient patient)
    {
        if (patient.Passport == null)
        {
            throw new ArgumentException("Can't to update patient without passport");
        }
        var pasp = _passportRepository.GetById(patient.Id);
        if (pasp != null)
        {
            //ToDo: update fields for item from DB???
            _passportRepository.Update(patient.Passport);
        }
    }

    public IEnumerable<IDiagnosis> GetAllDiagnoses(IPatient patient)
    {
        return _diagnosisRepository.GetAllForPatient(patient.Id);
    }

    public IDiagnosis GetDiagnosis(IPatient patient, int number)
    {
        return _diagnosisRepository.Get(patient.Id, number);
    }

    public void AddDiagnosis(IPatient patient, IDiagnosis diag)
    {
        var currentDiagnoses = _diagnosisRepository.GetAllForPatient(patient.Id);

        diag.Number = currentDiagnoses.Any() ? currentDiagnoses.Max(x => x.Number) + 1 : 1;

        _diagnosisRepository.Create(patient.Id, diag);
    }

    public void UpdateDiagnosis(IPatient patient, IDiagnosis diag)
    {
        var d = _diagnosisRepository.Get(patient.Id, diag.Number);
        if (d != null)
        {
            _diagnosisRepository.Update(patient.Id, diag);
        }
    }

    public void DeleteDiagnosis(IPatient patient, IDiagnosis diag)
    {
        var d = _diagnosisRepository.Get(patient.Id, diag.Number);
        if (d != null)
        {
            _diagnosisRepository.Delete(d);
        }
    }

    public void AddClinicGroup(IPatient patient, IClinicalGroup clinicalGroup)
    {
        _clinicalGroupsRepository.Create(patient.Id, clinicalGroup);
    }

    public void UpdateClinicalGroup(IPatient patient, IClinicalGroup clinicalGroup)
    {
        _clinicalGroupsRepository.Update(patient.Id, clinicalGroup);
    }

    public void DeleteClinicalGroup(IPatient patient, IClinicalGroup clinicalGroup)
    {
        _clinicalGroupsRepository.Delete(clinicalGroup);
    }

    public IEnumerable<IPatient> FindBy(IPatientSearchPattern pattern)
    {
        var pasports = _passportRepository.GetByExpression(pattern);
        return pasports.Select(x => new Patient(x));
    }

    public IEnumerable<IDispensaryMark> GetAllDispensaryMarks(IPatient patient)
    {
        return _dispensaryMarkRepository.GetAllForPatient(patient.Id);
    }

    public IDispensaryMark GetDispensaryMark(int identity)
    {
        Expression<Func<IDispensaryMark, bool>> identityExpression = x => x.Identity == identity;
        return _dispensaryMarkRepository.GetByIdentity(identity);
    }

    public void UpdateDispensaryMark(IDispensaryMark mark, int identity)
    {
        var dbMark = GetDispensaryMark(identity);
        if (dbMark != null)
        {
            _dispensaryMarkRepository.UpdateByIdentity(identity, mark);
        }
        else
        {
            throw new ArgumentException("There is no such dispensary mark ");
        }
    }

    public void DeleteDispensaryMark(int identity)
    {
        var dbMark = GetDispensaryMark(identity);
        if (dbMark != null)
        {
            _dispensaryMarkRepository.DeleteByKey(dbMark);
        }
        else
        {
            throw new ArgumentException("There is no such dispensary mark ");
        }

    }

    public void AddDispensaryMark(IPatient patient, IDispensaryMark mark)
    {
        _dispensaryMarkRepository.Create(patient.Id, mark);
    }

    public IEnumerable<ISendCall> GetSendedCalls(IPatient patient)
    {
        return _sendCallRepository.GetAllForPatient(patient.Id);
    }

    public void DeleteSendCall(ISendCall call)
    {
        _sendCallRepository.DeleteEntity(call);
    }

    public ISendCall GetSendCallByIdentity(int identity)
    {
        return _sendCallRepository.GetByIdentity(identity);
    }
}

Support Code-Contracts

Since AI modifies assembly before Code contracts, we have to inject code after code contracts notions

[BUG] Compilation Error if use Aspect from another Portable Library .dll

Steps to reproduce:

  1. Create portable .dll
  2. Move TraceAspect there.
  3. Create Console App. with TestClass
  4. Link portable .dll to Console App
  5. Mark TestClass with attribute [Aspect(typeof(TraceAspect))]
  6. Try to compile.

Error 2 InvalidCastException: Unable to cast object of type 'Mono.Cecil.TypeReference' to type 'Mono.Cecil.TypeDefinition'.
at AspectInjector.BuildTask.Processors.ModuleProcessors.InjectionProcessor.<>c__DisplayClassd.b__a(CustomAttribute attr)
at System.Linq.Enumerable.WhereSelectListIterator2.MoveNext() at System.Linq.Enumerable.WhereEnumerableIterator1.MoveNext()
at System.Collections.Generic.List1..ctor(IEnumerable1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable1 source) at AspectInjector.BuildTask.Processors.ModuleProcessors.InjectionProcessor.ProcessAspectAttributes(MethodDefinition targetMethod, String targetName, IEnumerable1 aspectAttributes)
at AspectInjector.BuildTask.Processors.ModuleProcessors.InjectionProcessor.ProcessModule(ModuleDefinition module)
at AspectInjector.BuildTask.Processors.AssemblyProcessor.Process(AssemblyDefinition assembly)
at AspectInjector.BuildTask.AspectInjectorBuildTask.Execute()
ConsoleApplication2

[BUG] There is ArgumentException during compilation in version 0.9.30

Error 202 ArgumentException: Member 'System.Exception' is declared in another module and needs to be imported
at Mono.Cecil.MetadataBuilder.LookupToken(IMetadataTokenProvider provider)
at Mono.Cecil.SignatureWriter.WriteTypeSignature(TypeReference type)
at Mono.Cecil.SignatureWriter.WriteMethodSignature(IMethodSignature method)
at Mono.Cecil.MetadataBuilder.GetMemberRefSignature(MemberReference member)
at Mono.Cecil.MetadataBuilder.CreateMemberRefRow(MemberReference member)
at Mono.Cecil.MetadataBuilder.GetMemberRefToken(MemberReference member)
at Mono.Cecil.MetadataBuilder.LookupToken(IMetadataTokenProvider provider)
at Mono.Cecil.Cil.CodeWriter.WriteOperand(Instruction instruction)
at Mono.Cecil.Cil.CodeWriter.WriteInstructions()
at Mono.Cecil.Cil.CodeWriter.WriteResolvedMethodBody(MethodDefinition method)
at Mono.Cecil.Cil.CodeWriter.WriteMethodBody(MethodDefinition method)
at Mono.Cecil.MetadataBuilder.AddMethod(MethodDefinition method)
at Mono.Cecil.MetadataBuilder.AddMethods(TypeDefinition type)
at Mono.Cecil.MetadataBuilder.AddType(TypeDefinition type)
at Mono.Cecil.MetadataBuilder.AddTypeDefs()
at Mono.Cecil.MetadataBuilder.BuildTypes()
at Mono.Cecil.MetadataBuilder.BuildModule()
at Mono.Cecil.ModuleWriter.b__0(MetadataBuilder builder, MetadataReader _)
at Mono.Cecil.ModuleDefinition.Read[TItem,TRet](TItem item, Func`3 read)
at Mono.Cecil.ModuleWriter.BuildMetadata(ModuleDefinition module, MetadataBuilder metadata)
at Mono.Cecil.ModuleWriter.WriteModuleTo(ModuleDefinition module, Stream stream, WriterParameters parameters)
at Mono.Cecil.ModuleDefinition.Write(Stream stream, WriterParameters parameters)
at Mono.Cecil.ModuleDefinition.Write(String fileName, WriterParameters parameters)
at AspectInjector.BuildTask.AspectInjectorBuildTask.Execute()
OR.Data.Core

Problem with generics

This code fails with "Unhandled Exception: System.BadImageFormatException: An attempt was made to load a program with an incorrect format."

using AspectInjector.Broker;
using System;

namespace ReproduceBug
{
    class Program
    {
        class EmptyAspect
        {
            [Advice(InjectionPoints.Around, InjectionTargets.Method)]
            public object GetResult(
            [AdviceArgument(AdviceArgumentSource.Target)] Func<object[], object> target,
            [AdviceArgument(AdviceArgumentSource.Arguments)] object[] args)
            {
                return target.Invoke(args);
            }
        }

        [Aspect(typeof(EmptyAspect))]
        static string Execute<T>(T input)
        {
            return input.ToString();
        }

        static void Main(string[] args)
        {
            Execute(0);
        }
    }
}

Static methods causes a runtime error

If I put an aspect on a static method I get the following runtime error when the method is called:
"Common Language Runtime detected an invalid program"

I am using version 0.9.44

Error when ctor call : this()

Exception error:

Exception: Cannot find base class ctor call
at AspectInjector.BuildTask.Extensions.MemberExtensions.FindBaseClassCtorCall(MethodDefinition md)
at AspectInjector.BuildTask.Contexts.TargetMethodContext.SetupEntryPoints()
at AspectInjector.BuildTask.Contexts.TargetMethodContext..ctor(MethodDefinition targetMethod)
at AspectInjector.BuildTask.Contexts.MethodContextFactory.GetOrCreateContext(MethodDefinition md)
at AspectInjector.BuildTask.Contexts.TypeContextFactory.b__2(MethodDefinition c)
at System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext() at System.Linq.Buffer1..ctor(IEnumerable1 source) at System.Linq.Enumerable.ToArray[TSource](IEnumerable1 source)
at AspectInjector.BuildTask.Contexts.TypeContextFactory.GetOrCreateContext(TypeDefinition td)
at AspectInjector.BuildTask.Processors.ModuleProcessors.InjectionProcessor.<>c__DisplayClass12.b__f(AspectDefinition def)
at System.Linq.Enumerable.WhereSelectListIterator2.MoveNext() at System.Linq.Enumerable.WhereEnumerableIterator1.MoveNext()
at System.Collections.Generic.List1..ctor(IEnumerable1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable1 source) at AspectInjector.BuildTask.Processors.ModuleProcessors.InjectionProcessor.ProcessAspectDefinitions(MethodDefinition targetMethod, String targetName, IEnumerable1 aspectDefinitions)
at AspectInjector.BuildTask.Processors.ModuleProcessors.InjectionProcessor.ProcessModule(ModuleDefinition module)
at AspectInjector.BuildTask.Processors.AssemblyProcessor.Process(AssemblyDefinition assembly)
at AspectInjector.BuildTask.AspectInjectorBuildTask.Execute()

Class to getenerate error:
public class Runner
{
public Runner() : this(0)
{
}
public Runner(int a)
{
}

    [Aspect(typeof(Trace))]
    public void Method()
    {
    }

}

Add AbortFlag to Exception InjectionPoint

It should be possible to suppress the exception after handling.

        [Advice(InjectionPoints.Before, InjectionTargets.Method)]
        public void HandleException(
            [Arg(Source.Instance)] Object owner,
            [Arg(Source.TargetException)] Exception targetException)
        {
            UiHelper.ShowError((FrameworkElement)owner, targetException);
            //TODO: don't throw the exception
        }

[BUG] InjectionPoints.Around is not working in static method

static void Main(string[] args)
{
    var value = GetLengthLong("Text");
}

[Aspect(typeof(StopwatchAspect))]
public static Int32 GetLengthLong(String text)
{
    Thread.Sleep(2000);
    return text.Length;
}

class StopwatchAspect
{
    [Advice(InjectionPoints.Around, InjectionTargets.Method)]
    public Object New(
        [AdviceArgument(AdviceArgumentSource.Name)] String name,
        [AdviceArgument(AdviceArgumentSource.Arguments)] Object[] args,
        [AdviceArgument(AdviceArgumentSource.Target)] Func<Object[], Object> target)
    {
        var sw = Stopwatch.StartNew();

        var returnValue = target(args);

        sw.Stop();

        Console.WriteLine("'{0}' Executed in {1} seconds", name, 
                              sw.ElapsedMilliseconds / 1000);

        return returnValue;
    }
}

An unhandled exception of type 'System.InvalidProgramException' occurred in ConsoleApplication1.exe

Additional information: JIT Compiler encountered an internal limitation

Support of Argument(Source) in ctor or AspectFactoryAttribute of aspect

Currently there is no other way to get AdviceArgumentSource.Instance (please correct me if I'm wrong) except of using [AdviceArgument(AdviceArgumentSource.Instance)] in [Advice(InjectionPoints.Before, InjectionTargets.Setter)](or similar). This creates an overhead because it is passed every time Advice is called and it is the same(instance value cannot be changed). My suggestion is to allow using AdviceArgumentSource.Instance in ctor or/and in AspectFactoryAttribute. So user has the ability to get values that don't change only once, without stack overhead.

Compilation issue when not providing a getter when injecting around a property setter

I have an aspect that is set up to inject before a property setter, I've found that I get the below compilation issue if I only provide a setter on the property. The compilation issue goes away when a getter is provided.

AspectInjector.0.9.44\build\AspectInjector.targets(5,5): error : NullReferenceException: Object reference not set to an instance of an object.
AspectInjector.0.9.44\build\AspectInjector.targets(5,5): error : at AspectInjector.BuildTask.Contexts.TargetMethodContext.get_MethodResultVariable()
AspectInjector.0.9.44\build\AspectInjector.targets(5,5): error : at AspectInjector.BuildTask.Injectors.AdviceInjector.InjectMethodCallWithResultReplacement(AdviceInjectionContext context, Instruction injectionPoint, Instruction returnPoint, FieldReference sourceMember)
AspectInjector.0.9.44\build\AspectInjector.targets(5,5): error : at AspectInjector.BuildTask.Injectors.AdviceInjector.Inject(AdviceInjectionContext context)
AspectInjector.0.9.44\build\AspectInjector.targets(5,5): error : at AspectInjector.BuildTask.Processors.AspectProcessors.AdviceProcessor.Process(AspectContext context)
AspectInjector.0.9.44\build\AspectInjector.targets(5,5): error : at AspectInjector.BuildTask.Processors.ModuleProcessors.InjectionProcessor.ProcessAspectDefinitions(MethodDefinition targetMethod, String targetName, IEnumerable`1 aspectDefinitions)
AspectInjector.0.9.44\build\AspectInjector.targets(5,5): error : at AspectInjector.BuildTask.Processors.ModuleProcessors.InjectionProcessor.ProcessModule(ModuleDefinition module)
AspectInjector.0.9.44\build\AspectInjector.targets(5,5): error : at AspectInjector.BuildTask.Processors.AssemblyProcessor.Process(AssemblyDefinition assembly)
AspectInjector.0.9.44\build\AspectInjector.targets(5,5): error : at
AspectInjector.BuildTask.AspectInjectorBuildTask.Execute()

My aspect is set up like below
[Advice( InjectionPoints.Before, InjectionTargets.Setter )] public void BeforePropertySetterSecurityCheck( [AdviceArgument( AdviceArgumentSource.AbortFlag )] ref bool abortFlag, [AdviceArgument( AdviceArgumentSource.RoutableData )] object data, [AdviceArgument( AdviceArgumentSource.Instance )] object instance )

and applied on the property like this

[UserRoleRequired( "Basic") ] public int SomeProperty { set { } }

Not working with Visual Studio

The aspect injector does not kick in when i build from VisualStudio. It works when I run msbuild from command line. I see the following statements in console.

"Assembly has been loaded"
"Assembly has been patched"
"Assembly has been written"

But, when i build it from VS, I don't see these lines and the aspect injector attribute doesn't work. Am i missing something here?

Make Janitor's CompilationExceptions point to Instruction

now in case a method references a type from broker - we fire

throw new CompilationException("Types from AspectInjector.Broker can't be referenced", method);

instead we need to point to exact line of code, like this

throw new CompilationException("Types from AspectInjector.Broker can't be referenced", instruction);

[BUG] AdviceArgumentSource.Method is not working

  1. Build error - NotSupportedException: Cannot resolve type of System.Reflection.MethodInfo
static void Main(string[] args)
{
    var p = new Program();
    p.GetLengthLong();
}

[Aspect(typeof(LoggingAspect))]
public void GetLengthLong()
{
    Thread.Sleep(2000);
}

class LoggingAspect
{
    [Advice(InjectionPoints.Before, InjectionTargets.Method)]
    public void Log([AdviceArgument(AdviceArgumentSource.Method)] MethodInfo method)
    {
        Console.WriteLine("Calling '{0}'", method.ToString());
    }
}
  1. Type of variable "MethodInfo" is not correct, because constructor returns "MethodBase"
[Aspect(typeof(LoggingAspect))]
class Program
{
    static Program()
    {
        Log(MethodBase.GetCurrentMethod());
    }

    Program()
    {
        Log(MethodBase.GetCurrentMethod());
    }

    static void Main(string[] args)
    {
        var p = new Program();
        Log(MethodBase.GetCurrentMethod());
    }

    public static void Log(MethodBase method)
    {
        var baseType = method is MethodInfo ? "Info" : "Base";
        Console.WriteLine("Type of method '{0}' is '{1} : Method{2}'", method.ToString(), 
              method.GetType().Name, baseType);
    }

    class LoggingAspect
    {
        [Advice(InjectionPoints.Before, InjectionTargets.Constructor)]
        public void Log([AdviceArgument(AdviceArgumentSource.Name)] String name
              /*, [AdviceArgument(AdviceArgumentSource.Method)] MethodBase method*/)
        {
            Console.WriteLine("Calling '{0}'", name);
        }
    }
}

Result

[NEW FEATURE] Add AdviceArgumentSource.Tag

For example:

    class Program
    {
        private static StopwatchAspect _StopwatchAspect = new StopwatchAspect();

        static void Main(string[] args)
        {
            var p = new Program();
            p.Test2();
        }

        [Aspect(typeof(StopwatchAspect))]
        public void Test()
        {
            Thread.Sleep(2000);
        }

        public void Test2()
        {
            Stopwatch tag = null;
            _StopwatchAspect.Start(ref tag);
            Thread.Sleep(2000);
            _StopwatchAspect.Stop("Test2", ref tag);
        }
    }

    class StopwatchAspect
    {
        [Advice(InjectionPoints.Before, InjectionTargets.Method)]
        public void Start([AdviceArgument(AdviceArgumentSource.Tag)] ref Stopwatch sw)
        {
            sw = Stopwatch.StartNew();
        }

        [Advice(InjectionPoints.After, InjectionTargets.Method)]
        public void Stop(
            [AdviceArgument(AdviceArgumentSource.TargetName)] String name,
            [AdviceArgument(AdviceArgumentSource.Tag)] ref Stopwatch sw)
        {
            sw.Stop();

            Console.WriteLine("'{0}' Executed in {1} seconds", name, sw.ElapsedMilliseconds / 1000);
        }
    }

Net Core support

Hi.

I'm investigating your library. It looks like very flexible solution for AOP.

I've tried to use it in Net Core projects but it doesn't look to work.

  1. I just created empty console app based on Net Core.
  2. Added your lib and changed Framework to 4.6.1 in project.json:
{
  "version": "1.0.0-*",
  "buildOptions": {
    "emitEntryPoint": true
  },

  "dependencies": {
    "AspectInjector": "1.0.0-beta4"
  },

  "frameworks": {
    "net461": {
    }
  }
}
  1. Added test code:
using System;

namespace AspectInjectorTest
{
    using AspectInjector.Broker;

    public class Program
    {
        public static void Main(string[] args)
        {
            var container = new Container();

            container.Load();
            container.Load();
            container.Save();

            Console.ReadLine();
        }
    }


    [Aspect(typeof(TraceAspect))]
    public class Container
    {
        public string Name { get; set; }

        public void Load() { }
        public void Save() { }
    }

    public class TraceAspect
    {
        private int count;

        [Advice(InjectionPoints.Before, InjectionTargets.Method)]
        public void CallCountTrace()
        {
            Console.WriteLine("Call #{0}", count);
            count++;
        }
    }
}

It doesn't show any errors but in console is nothing. The same sample work in previous .Net.

Will you add support of .Net Core for this lib?

Regards.
Igor.

[BUG] There is Exception if you try to set Aspect to class which is inherited from generic one

Steps to reproduce:

  1. Create generic class BaseClass
  2. Create another ConcreteClass and inherit from BaseClass
  3. Create ctor in ConcreteClass and use base ctor as well
  4. Mark ConcreteClass with [Aspect(typeof(TraceAspect))]

Error 202 Exception: Cannot find base class ctor call
at AspectInjector.BuildTask.Extensions.MemberExtensions.FindBaseClassCtorCall(MethodDefinition md)
at AspectInjector.BuildTask.Contexts.TargetMethodContext.SetupEntryPoints()
at AspectInjector.BuildTask.Contexts.TargetMethodContext..ctor(MethodDefinition targetMethod)
at AspectInjector.BuildTask.Contexts.MethodContextFactory.GetOrCreateContext(MethodDefinition md)
at AspectInjector.BuildTask.Contexts.TypeContextFactory.b__2(MethodDefinition c)
at System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext() at System.Linq.Buffer1..ctor(IEnumerable1 source) at System.Linq.Enumerable.ToArray[TSource](IEnumerable1 source)
at AspectInjector.BuildTask.Contexts.TypeContextFactory.GetOrCreateContext(TypeDefinition td)
at AspectInjector.BuildTask.Processors.ModuleProcessors.InjectionProcessor.<>c__DisplayClassd.b__a(CustomAttribute attr)
at System.Linq.Enumerable.WhereSelectListIterator2.MoveNext() at System.Linq.Enumerable.WhereEnumerableIterator1.MoveNext()
at System.Collections.Generic.List1..ctor(IEnumerable1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable1 source) at AspectInjector.BuildTask.Processors.ModuleProcessors.InjectionProcessor.ProcessAspectAttributes(MethodDefinition targetMethod, String targetName, IEnumerable1 aspectAttributes)
at AspectInjector.BuildTask.Processors.ModuleProcessors.InjectionProcessor.ProcessModule(ModuleDefinition module)
at AspectInjector.BuildTask.Processors.AssemblyProcessor.Process(AssemblyDefinition assembly)
at AspectInjector.BuildTask.AspectInjectorBuildTask.Execute()
OR.WebApplication

Error at cleaning up references to the Broker assembly

InvalidCastException: Unable to cast object of type 'Mono.Cecil.GenericInstanceMethod' to type 'Mono.Cecil.TypeReference'.
at AspectInjector.BuildTask.Processors.ModuleProcessors.Janitor.IsInstructionReferencesBroker(Instruction instruction)
at System.Linq.Enumerable.Any[TSource](IEnumerable1 source, Func2 predicate)
at AspectInjector.BuildTask.Processors.ModuleProcessors.Janitor.IsMethodBodyReferencesBroker(MethodBody methodBody)
at AspectInjector.BuildTask.Processors.ModuleProcessors.Janitor.CheckMethodReferencesBroker(MethodDefinition method)
at System.Collections.Generic.List1.ForEach(Action1 action)
at AspectInjector.BuildTask.Processors.ModuleProcessors.Janitor.CheckTypeReferencesBroker(TypeDefinition type)
at System.Collections.Generic.List1.ForEach(Action1 action)
at AspectInjector.BuildTask.Processors.ModuleProcessors.Janitor.ProcessModule(ModuleDefinition module)
at AspectInjector.BuildTask.Processors.AssemblyProcessor.Process(AssemblyDefinition assembly)
at AspectInjector.BuildTask.AspectInjectorBuildTask.Execute()

Not throw TaskCanceledException

Version 1.0.0-beta4
I'm test this code:

    public class StupidAspect
    {
        [Advice(InjectionPoints.Before, InjectionTargets.Method)]
        public void StartMethod([AdviceArgument(AdviceArgumentSource.Name)]string methodName)
        {
            Console.WriteLine("start " + methodName);
        }

        [Advice(InjectionPoints.After, InjectionTargets.Method)]
        public void StopMethood([AdviceArgument(AdviceArgumentSource.Name)]string methodName)
        {
            Console.WriteLine("end " + methodName);
        }        
    }

    [Aspect(typeof(StupidAspect))]
    public class TestClass
    {
        CancellationToken token;
        private CancellationTokenSource cancellationTokenSource;

        public TestClass()
        {
            cancellationTokenSource = new CancellationTokenSource();
            token = cancellationTokenSource.Token;
        }

        public async Task Start()
        {
            await Method1();
        }

        private async Task Method1()
        {
            try
            {
                await Wait(); // must throw exception
            }
            catch (Exception exp)
            {
                Console.WriteLine("Operation cancel");
            }
        }

        private async Task Wait()
        {
            await Task.Delay(10000, token);
        }

        public void Cancel()
        {
            cancellationTokenSource.Cancel();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            TestClass testClass = new TestClass();
            testClass.Start();
            testClass.Cancel();
            Console.ReadKey();
        }
    }

Console output:

start Start
start Method1
start Wait
start Cancel
end Cancel
end Wait
end Method1
end Start

Must be:

start Start
start Method1
start Wait
start Cancel
Operation cancel
end Cancel
end Wait
end Method1
end Start

Make TargetValue (former TargetReturnValue) contain oldvalue ( getter(); ) for InjectionTargets.Setter

This can be easily done via reflection, but it requires extra overhead for each new instance. As far as I understand, if this is done the same way as the others AdviceArgumentSource, there will be now overhead. For InjectionTargets.Getter return both Getter and Setter MethodInfo. Same for InjectionTargets. Add and InjectionTargets.EventRemove.

Some use case: implement INotifyPropertyChanged and check if property is changed.
In the current version I cannot do anything better than(maybe there is a better way?):

        private bool _hasChanged;
        private MethodInfo _getter;

        [Advice(InjectionPoints.Before, InjectionTargets.Setter)]
        public void NotifyChangeBefore([AdviceArgument(AdviceArgumentSource.Instance)] object instance,
                                       [AdviceArgument(AdviceArgumentSource.TargetName)] string name,
                                       [AdviceArgument(AdviceArgumentSource.TargetArguments)] object[] parameters,
                                        [AdviceArgument(AdviceArgumentSource.AbortFlag)] ref bool abort)
        {
            if (_getter == null)
            {
                var t = instance.GetType();
                var p = t.GetProperties().Single(info => info.Name == name);

                _getter = p.GetGetMethod();
            }

            var oldValue = _getter.Invoke(instance, null);
            var newValue = parameters.Single();

            _hasChanged = !Equals(oldValue, newValue);
            if (!_hasChanged)
                abort = true;
        }

InvalidProgramException at calling static method with AdviceArgumentSource.Instance attribute

public class MyAspect
{
    [Advice(InjectionPoints.Before, InjectionTargets.Method)]
    public void AspectMethodRealization(
        [AdviceArgument(AdviceArgumentSource.Instance)] object instance)
    {
        Console.WriteLine("Aspect Works!!!");
    }
}

[Aspect(typeof(MyAspect))]
public static class MyStatic
{
    public static void StaticTest()
    {
        Console.WriteLine("Static Test");
    }
}

class Program
{
    static void Main(string[] args)
    {
        MyStatic.StaticTest();
    }
}

System.InvalidProgramException with message "Common Language Runtime detected an invalid program." appears at 'MyStatic.StaticTest();' line. If remove parameter 'object instance' from AspectMethodRealization() - all good.

In my case i need to read CustomAttributes of target method. Also i need to detect IsPublic or IsPrivate properties of target method (method can be static or non-static, does not matter for me). In previous realization (PostSharp) i do it by reflection (a have MethodBase object for target method), but now a have only TargetName property. So i need to correct Instanse property for getting MathodBase property. Or is there some another way to do it?

"base" equals "this" in overriden method

I have two classes: Base and Child. There is a method in Base that's overriden in Child and that has an Around aspect. Overriden method calls base implementation, but it calls himself instead resulting in StackOverflow exception.
base.GetType() == this.GetType() returns true

[BUG] InjectionPoints.Around is not working with InjectionTargets.Constructor

Error: An unhandled exception of type 'System.TypeLoadException' occurred in mscorlib.dll

Source:

[Aspect(typeof(LoggingAspect))]
class Program
{
    static Program()
    {
        Console.WriteLine("Processing .cctor");
    }

    public Program()
    {
        Console.WriteLine("Processing .ctor");
    }

    static void Main(string[] args)
    {
        var p = new Program();
    }
}
class LoggingAspect
{
    [Advice(InjectionPoints.Around, InjectionTargets.Constructor)]
    public Object Log(
        [AdviceArgument(AdviceArgumentSource.Name)] String name,
        [AdviceArgument(AdviceArgumentSource.Arguments)] Object[] args,
        [AdviceArgument(AdviceArgumentSource.Target)] Func<Object[], Object> target)
    {
        Console.WriteLine("Calling '{0}'", name);
        var ret = target(args);
        Console.WriteLine("Called '{0}'\n", name);
        return ret;
    }
}

Compiled source:

internal class Program
{
    private static LoggingAspect __a$_LoggingAspect;
    static Program()
    {
        object[] array = new object[0];
        object obj = Program.__a$w0_.cctor(array);
    }
    public Program()
    {
        object[] array = new object[0];
        object obj = this.__a$w0_.ctor(array);
    }
    private static void Main(string[] args)
    {
        Program p = new Program();
    }
    private static void __a$_initializeTypeAspects()
    {
        if (Program.__a$_LoggingAspect == null)
        {
            Program.__a$_LoggingAspect = new LoggingAspect();
        }
    }
    private static void cctor()
    {
        Program.__a$_initializeTypeAspects();
        Console.WriteLine("Processing .cctor");
    }
    [DebuggerHidden, CompilerGenerated]
    private static object cctor(object[] array)
    {
        Program.__a$o_.cctor();
        return null;
    }
    [DebuggerHidden, CompilerGenerated]
    private static object cctor(object[] args)
    {
        return Program.__a$_LoggingAspect.Log(".cctor", args, delegate
        {
            Program.__a$o_.cctor();
            return null;
        });
    }
    public void ctor()
    {
        base..ctor();
        Console.WriteLine("Processing .ctor");
    }
    [DebuggerHidden, CompilerGenerated]
    public object ctor(object[] array)
    {
        this.__a$o_.ctor();
        return null;
    }
    [DebuggerHidden, CompilerGenerated]
    public object ctor(object[] args)
    {
        return Program.__a$_LoggingAspect.Log(".ctor", args, delegate
        {
            this.__a$o_.ctor();
            return null;
        });
    }
}

Mono compatibility

Hi.

Trying to use Your library on linux with mono. Created simple aspect and trying to compile project with xbuild. Got next error on build stage:

Aspect Injector has started for TestAspectInjector.exe
Assembly has been loaded
Assembly has been patched
Assembly has been written
: error : Error building target AfterCompile: Exception has been thrown by the target of an invocation.
Done building project "/opt/TestAspectInjector/TestAspectInjector.csproj".-- FAILED

Is it compatible with mono?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.