SoFunction
Updated on 2025-03-04

Caizha open source AOP library (.NET Core) based on EMIT

Nuget library address:/packages//

Github library address:/whuanle/

It is a simple and lightweight AOP framework written based on EMIT, supports non-invasive proxy, supports .NET Core/Core, and supports multiple dependency injection frameworks.

1. Quick Start

Use is relatively simple, you only need to use[Interceptor]Feature tags the type that requires proxy, and then use inheritanceActionAttributeThe attribute marks the method or attribute to be proxyed.

1.1 Inheriting ActionAttribute Features

ActionAttributeIt is a feature mark used for proxy methods or attributes. It cannot be used directly. The method needs to be inherited and rewrited.

Examples are as follows:

    public class LogAttribute : ActionAttribute
    {
        public override void Before(AspectContext context)
        {
            ("Before execution");
        }
        public override object After(AspectContext context)
        {
            ("After execution");
            if ()
                return ;
            else if ()
                return ;
            return null;
        }
    }

BeforeIt will take effect before the proxy method is executed or when the proxy attribute is called, you can useAspectContextContext, obtain and modify passed parameters.

After takes effect after the method is executed or when the property is called, you can get and modify the return value through the context.

1.2 Tag proxy type

In the type being proxyed, use[Interceptor]Features are marked, and in methods that require proxy, inheritedActionAttributecharacteristics to mark.

This method is invasive and needs to be done before compilation.

[Interceptor]
public class Test : ITest
{
    [Log] public virtual string A { get; set; }
    [Log]
    public virtual void MyMethod()
    {
        ("Running");
    }
}

Note that a method or property can only set one interceptor.

2. How to create a proxy type

There are many ways to generate proxy types, and the following is a simple way.

Please create the following code in advance:

    public class LogAttribute : ActionAttribute
    {
        public override void Before(AspectContext context)
        {
            ("Before execution");
        }
        public override object After(AspectContext context)
        {
            ("After execution");
            if ()
                return ;
            else if ()
                return ;
            return null;
        }
    }
    public interface ITest
    {
        void MyMethod();
    }
    [Interceptor]
    public class Test : ITest
    {
        [Log] public virtual string A { get; set; }
        public Test()
        {
            ("Constructor is OK");
        }
        [Log]
        public virtual void MyMethod()
        {
            ("Running");
        }
    }

2.1 Create directly through the API

ByAopInterceptorClass, you can generate proxy types.

Examples are as follows:

            ITest test1 = <ITest, Test>();
            Test test2 = <Test>();
            ();
            ();

CreateProxyOfInterfaceCreate proxy types through interfaces;CreateProxyOfClassCreate proxy types through classes;

The default call is the parameterless constructor.

3. Create a proxy type

Through API

You can refer to the source code solution

The ExampleConsole project in .

If you want to use it directlyandMethod, create proxy types through interfaces or classes.

        ITest test1 = <ITest, Test>();
        Test test2 = <Test>();

If you want to specify an instantiated constructor, you can do this:

            // Specify the constructor            test2 = &lt;Test&gt;("aaa", "bbb");
            ();

pass

is the default dependency injection container for .NET Core/Core.

If you need to support the use of AOP in Core, you can install it in the Nuget package.

If you use it under the console, you can use the nameBuildAopProxyofIServiceCollectionExpand method to generate proxy types for the types in the container.

Examples are as follows:

            IServiceCollection _services = new ServiceCollection();
            _services.AddTransient<ITest, Test>();
            var serviceProvider = _services.BuildAopProxy().BuildServiceProvider();
            <ITest>();
            return serviceProvider;

You can refer to the source code solutionExampleMEDIproject.

If you want to use it in Core, you canStartupmiddle,ConfigureServicesThe last line of code of the method is used(); 。

        public void ConfigureServices(IServiceCollection services)
        {
            ();
            ();
        }

Can also be inProgramofIHostBuilderUsed in.UseServiceProviderFactory(new AOPServiceProxviderFactory())To configure and use .

Example:

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            (args)
            .UseServiceProviderFactory(new AOPServiceProxviderFactory())
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    <Startup>();
                });

You can refer to the solutionExampleConsoleandExampleWebMEDITwo projects.

You don't have to worry that using dependency injection will slow down the program or destroy the original properties in the container after introduction. Only the types that need to be proxyed will be processed when creating the container, and will not affect the services in the container, nor will it interfere with the execution of dependency injection.

By Autofac

If you need to use AOP in Autofac, you need to referenceBag.

If you use Autofac in a console program, you canBuild()Use laterBuildAopProxy()

            ContainerBuilder builder = new ContainerBuilder();
            &lt;Test&gt;().As&lt;ITest&gt;();
            var container = ().BuildAopProxy();
            using (ILifetimeScope scope = ())
            {
                // Get an instance                ITest myService = &lt;ITest&gt;();
                ();
            }
            ();
        }

It should be noted that it can only be called after the completed component registration creates a new container.BuildAopProxy()method,

In this way, for a new container, you can consider whether you need to proxy components in the container.

If you use Autofac in Core, you need to use it in the IHostBuilder of the Program class:

.UseServiceProviderFactory(new AutofacServiceProviderFactory())

If you need a component that the proxy has registered, replace it with:

 .UseServiceProviderFactory(new ())

Please refer to the source code solutionExampleAutofacandExampleWebAutofacTwo projects.

4. In-depth use

Agent Type

The type to be proxy needs to be used[Interceptor]To mark, for example:

    [Interceptor]
    public class Test : ITest
    {
    }

Supports generic types.

The type that is proxy must be inheritable.

There are no restrictions on the constructor of the type, you can write it as you like.

When creating a proxy type using the API and instantiating it, you can specify which constructor to use.

For example:

string a="",b="",c="";
			ITest test1 = <ITest, Test>(a,b,c);

The API will automatically find the appropriate constructor based on the number of parameters and the type of parameters.

Methods, attribute agents

In order to proxy methods or attributes, you need to inheritActionAttributeProperties, then mark this property for the method or attribute, and set the method or attribute tovirtual

Different methods in a type can use different interceptors.

        [Log1]
        public virtual void MyMethod1(){}
        [Log2]
        public virtual void MyMethod2(){}

For properties, you can use the properties directly on the properties, or only in the get or set constructor.

        [Log] public virtual string A { get; set; }
        // or        public virtual string A { [Log] get; set; }
        // or        public virtual string A { get; [Log] set; }

If you use characteristics on attributes, it is equivalent to[Log] get; [Log] set;

Context

A simple method or property intercept tag is like this:

    public class LogAttribute : ActionAttribute
    {
        public override void Before(AspectContext context)
        {
            ("Before execution");
        }
        public override object After(AspectContext context)
        {
            ("After execution");
            if ()
                return ;
            else if ()
                return ;
            return null;
        }
    }

The properties of AspectContext are described as follows:

Fields illustrate
Type The proxy type currently generated by the proxy type
ConstructorParamters The argument to the constructor used when the type is instantiated, = 0 if the constructor has no arguments, instead of MethodValues ​​being null.
IsProperty The current intercepted attributes
PropertyInfo The information of the currently executed attribute may be null.
PropertyValue But when the property is called, it returns the result of get or the value of set.
IsMethod The current intercepting method
MethodInfo Information about the current method
MethodValues Parameters passed when the method is called, if this method has no parameters, then = 0 instead of MethodValues ​​being null
MethodResult The result returned by the method execution (if any)

Intercepting parameters of methods or attributes

With the context, you can modify the parameters of a method or property and intercept the return result:

    public class LogAttribute : ActionAttribute
    {
        public override void Before(AspectContext context)
        {
            // Intercept and modify the method parameters            for (int i = 0; i &lt; ; i++)
            {
                [i] = (int)[i] + 1;
            }
            ("Before execution");
        }
        public override object After(AspectContext context)
        {
            ("After execution");
            // The execution result of the intercept method             = (int) + 664;
            if ()
                return ;
            else if ()
                return ;
            return null;
        }
    }
    [Interceptor]
    public class Test
    {
        [Log]
        public virtual int Sum(int a, int b)
        {
            ("Running");
            return a + b;
        }
    }
            Test test = <Test>();
            ((1, 1));

Method parameter supportinrefout;Support generic properties of generic methods; supports asynchronous methods;

Non-invasive proxy

This method does not require changing the type being proxyed, you can also proxy the type in the assembly set.

    public class LogAttribute : ActionAttribute
    {
        public override void Before(AspectContext context)
        {
            ("Before execution");
        }
        public override object After(AspectContext context)
        {
            ("After execution");
            if ()
                return ;
            else if ()
                return ;
            return null;
        }
    }
    public class TestNo
    {
        public virtual string A { get; set; }
        public virtual void MyMethod()
        {
            ("Running");
        }
    }
            TestNo test3 = <TestNo>(new ProxyTypeBuilder()
                .AddProxyMethod(typeof(LogAttribute), typeof(TestNo).GetMethod(nameof()))
                .AddProxyMethod(typeof(LogAttribute), typeof(TestNo).GetProperty(nameof()).GetSetMethod()));

Build the proxy type with ProxyTypeBuilder.

Both proxy methods or attributes are usedAddProxyMethod, the first parameter is the interceptor to be used, and the second parameter is the method to be intercepted.

If you want to intercept attributes, please set the attributes separately.getsetConstruction.

If multiple methods or properties use the same interceptor, you can do this:

            TestNo test3 = <TestNo>(
                new ProxyTypeBuilder(new Type[] { typeof(LogAttribute) })
                .AddProxyMethod("LogAttribute", typeof(TestNo).GetMethod(nameof()))
                .AddProxyMethod("LogAttribute", typeof(TestNo).GetProperty(nameof()).GetSetMethod()));
            TestNo test3 = <TestNo>(
                new ProxyTypeBuilder(new Type[] { typeof(LogAttribute) })
                .AddProxyMethod("LogAttribute", typeof(TestNo).GetMethod(nameof()))
                .AddProxyMethod(typeof(LogAttribute2), typeof(TestNo).GetProperty(nameof()).GetSetMethod()));

Pass the interceptor you need in the constructor and then use it when intercepting.

This is the end of this article about Caizha Open Source AOP library (.NET Core) based on EMIT. For more content related to EMIT AOP library, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!