All Projects → Virtuoze → Puresharp

Virtuoze / Puresharp

Licence: mit
Puresharp is a Framework that provides the essential APIs (AOP, IOC, etc...) to productively build high quality (.NET 4.5.2+ & .NET Core 2.1+) applications through reliability, scalability and performance without no compromise

Programming Languages

csharp
926 projects

Projects that are alternatives of or similar to Puresharp

CNeptune
CNeptune improve productivity & efficiency by urbanize .net module with meta-code to lay foundation for frameworks
Stars: ✭ 30 (-75%)
Mutual labels:  ioc, injection, aop
vesselize
⛵ A JavaScript IoC container that works seamlessly with Vue.js and React.
Stars: ✭ 22 (-81.67%)
Mutual labels:  ioc, composition, injection
Nconcern
NConcern .NET AOP Framework
Stars: ✭ 139 (+15.83%)
Mutual labels:  advice, aop, injection
Aspect Injector
AOP framework for .NET (c#, vb, etc)
Stars: ✭ 398 (+231.67%)
Mutual labels:  advice, aop, injection
Thunder
Stars: ✭ 70 (-41.67%)
Mutual labels:  ioc, aop
Swoft Framework
[READ ONLY] Swoft Framework, base of Swoft
Stars: ✭ 70 (-41.67%)
Mutual labels:  framework, aop
Devis
A microservices framework for Node.js
Stars: ✭ 72 (-40%)
Mutual labels:  framework, architecture
Proxy.py
⚡⚡⚡Fast, Lightweight, Pluggable, TLS interception capable proxy server focused on Network monitoring, controls & Application development, testing, debugging
Stars: ✭ 1,291 (+975.83%)
Mutual labels:  framework, proxy
Poodinis
A dependency injection framework for D with support for autowiring.
Stars: ✭ 57 (-52.5%)
Mutual labels:  ioc, injection
Container Ioc
Inversion of Control container & Dependency Injection for Javascript and Node.js apps powered by Typescript.
Stars: ✭ 89 (-25.83%)
Mutual labels:  ioc, injection
Gracejs
A Nodejs BFF framework, build with koa2(基于koa2的标准前后端分离框架)
Stars: ✭ 1,302 (+985%)
Mutual labels:  framework, proxy
Koatty
Koa2 + Typescript = Koatty. Use Typescript's decorator implement IOC and AOP.
Stars: ✭ 67 (-44.17%)
Mutual labels:  ioc, aop
Singularity
A extremely fast ioc container for high performance applications
Stars: ✭ 63 (-47.5%)
Mutual labels:  net, ioc
Lithium
li₃ is the fast, flexible and most RAD development framework for PHP
Stars: ✭ 1,176 (+880%)
Mutual labels:  framework, aop
Danf
Danf is a Node.js full-stack isomorphic OOP framework allowing to code the same way on both client and server sides. It helps you to make deep architectures and handle asynchronous flows in order to help in producing scalable, maintainable, testable and performant applications.
Stars: ✭ 58 (-51.67%)
Mutual labels:  framework, architecture
Doodle
A Simple Java MVC Framework。提供Bean容器、Ioc、Aop、MVC功能
Stars: ✭ 90 (-25%)
Mutual labels:  ioc, aop
Connective
agent-based reactive programming library for typescript
Stars: ✭ 98 (-18.33%)
Mutual labels:  framework, architecture
Agentframework
An elegant & efficient TypeScript metaprogramming API to build software agents
Stars: ✭ 97 (-19.17%)
Mutual labels:  proxy, aop
Aspnetboilerplate
ASP.NET Boilerplate - Web Application Framework
Stars: ✭ 10,061 (+8284.17%)
Mutual labels:  framework, architecture
Framework
💎 Go! AOP PHP - modern aspect-oriented framework for the new level of software development
Stars: ✭ 1,559 (+1199.17%)
Mutual labels:  framework, aop

Puresharp API .NET

Puresharp is a set of features for .NET 4.5.2+ / .NET Core 2.1 to improve productivity by producing flexible and efficient applications.

Overview

Puresharp mainly provides architectural tools to build the basics of professional applications :

  • Dependency Injection Container
  • Aspect Oriented Programming
  • Metadata Reflection API

This framework is divided into 2 parts :

  • IPuresharp   NuGet

IPuresharp is a nuget package dedicated to rewrite assemblies (using Mono.Cecil) to allow them to be highly customizable at runtime. IPuresharp won't add a new library reference to assmblies, but only include a post build process to automatically rewrite assemblies just after success build.

Install-Package IPuresharp -Version 5.0.5

It can be used manually with command line to manage third party assemblies

IPuresharp.exe "FullnameToAssembly.dll"
  • Puresharp   NuGet

Puresharp is a nuget package offering various features useful for designing a healthy and productive architecture. This package also includes all the artillery to easily handle the elements that brings the IL writer IPuresharp. The nuget package add a library (Puresharp.dll) without any other depencies.

Install-Package Puresharp -Version 5.0.5

note : It is recommanded to install IPuresharp nuget package in all projects and install Puresharp nuget package only in project where you explicitly need it.

Dependency Injection Container

The global workflow of the DI Container is similar to others : setup a composition, create a container and instantiate from container some components.

Preview

Example of interfaces to configure

public interface IA
{
}

public interface IB
{
}

public interface IC
{
}

Example of implementations to bind to interfaces

public class A : IA
{
    public A(IB b, IC c)
    {
    }
}

public class B : IB
{
    public B(IC c, int constant)
    {
    }
}

public class C : IC
{
}

Create a composition

var _composition = new Composition();

Setup composition for IA, IB, IC whith respectivily A, B, C

_composition.Setup<IA>(() => new A(Metadata<IB>.Value, Metadata<IC>.Value), Instantiation.Multiton);
_composition.Setup<IB>(() => new B(Metadata<IC>.Value, 28), Instantiation.Multiton);
_composition.Setup<IC>(() => new C(), Instantiation.Multiton);

Create a container from composition setup

var _container = _composition.Materialize();

Instantiate a module of IA from container

using (var _module = _container.Module<IA>())
{
    var _ia = _module.Value;
}

note : module is IDisposable and crontrol lifecycle for all dependencies.

FAQ

  • How is managed lifecycle for dependencies? When a module is setup into composition, instantiation mode is required and can be Singleton (a single instance with a lifecycle related to container), Multiton (a new instance for each module with lifecycle related to module itself) or Volatile (always a new instance with lifecycle related to owner module). Container and Module are both IDisposable to release created components.

  • Sould my interfaces implement IDisposable to match with lifecycle management? On the contrary, the interface of a component should never implement the IDisposable interface which is a purely infrastructure concern. Only implementations could possibly be. The container makes sure to dispose the implementations properly when it implements the IDisposable interface.

  • Why using lambda expression to configure components instead of classic generic parameter? Lambda expression offer a way to target constructor to use, specify when to use dependencies and capture constant.

  • How dependency is configured? Simply use Metadata<T>.Value in expression when you need to get back dependency from container.

  • Is constructor injection prevent cyclic reference between component? No, cyclic references are a feature. When an instance is created, it is not really the case, a lazy proxy instance is prepared to minimize unused resources retention and allow cyclic references.

  • In preview, only constructors are used to setup component, is it limited to constructor injection? No, expressions are totally open. You can inject static methods, constructors, members and even mix differents styles.

Aspect Oriented Programming

Workflow :

  • Identify group of methods by defining a Pointcut
  • Specify an Aspect by defining some Advices
  • Instantiate the Aspect and Weave it into Pointcut

Preview

Example of interface

[AttributeUsage(AttributeTargets.Method)]
public class Read : Attribute
{
}

[AttributeUsage(AttributeTargets.Method)]
public class Operation : Attribute
{
}

public interface IService
{
    [Operation]
    void SaveComment(int id, string text);

    [Read]
    [Operation]
    string GetComment(int id);
}

Example of implementation

public class Service : IService
{
    public void SaveComment(int id, string text)
    {
    }

    public string GetComment(int id)
    {
        return null;
    }
}

Supposed we want to log all readonly operations. For that, we have to define a Pointcut that represent all methods that are readonly operation (where Read attribute and Operation attribute are placed)

public class ReadonlyOperation : Pointcut.And<Pointcut<Operation>, Pointcut<Read>>
{
}

Define an Advice to log before whith Trace.WriteLine for exemple when calling methods

public class Log : IAdvice
{
    private MethodBase m_Method;

    public Log(MethodBase method)
    {
        this.m_Method = method;
    }

    public void Instance<T>(T instance)
    {
    }

    public void Argument<T>(ref T value)
    {
    }

    public void Begin()
    {
        Trace.WriteLine(this.m_Method);
    }

    public void Await(MethodInfo method, Task task)
    {
    }

    public void Await<T>(MethodInfo method, Task<T> task)
    {
    }
    
    public void Continue()
    {
    }
    
    public void Throw(ref Exception exception)
    {
    }

    public void Throw<T>(ref Exception exception, ref T value)
    {
    }

    public void Return()
    {
    }

    public void Return<T>(ref T value)
    {
    }
    
    public void Dispose()
    {
    }
}

Define an Aspect that use log Advice

public class Logging : Aspect
{
    override public IEnumerable<Advisor> Manage(MethodBase method)
    {
        yield return Advice
            .For(method)
            .Around(() => new Log(method));
    }
}

Instantiate Aspect and weave it to our ReadonlyOperation Pointcut

var _logging = new Logging();
_logging.Weave<ReadonlyOperation>();

Congratulation, the logging Aspect in now injected to all readonly operation contract.

Sample

Here a set of sample to let see differents way to create and advisor.

public class Logging : Aspect
{
    override public IEnumerable<Advisor> Manage(MethodBase method)
    {
        //Use classic interceptor to create an 'Around' advisor (place break points in interceptor methods to test interception).
        yield return Advice
            .For(method)
            .Around(() => new Interceptor());

        //Use linq expression to generate a 'Before' advisor.
        yield return Advice
            .For(method)
            .Before(invocation =>
            {
                return Expression.Call
                (
                    Metadata.Method(() => Console.WriteLine(Metadata<string>.Value)), 
                    Expression.Constant($"Expression : { method.Name }")
                );
            });

        //Use linq expression to generate a 'Before' advisor.
        yield return Advice
            .For(method)
            .Before
            (
                Expression.Call
                (
                    Metadata.Method(() => Console.WriteLine(Metadata<string>.Value)),
                    Expression.Constant($"Expression2 : { method.Name }")
                )
            );

        //Use ILGeneration from reflection emit API to generate a 'Before' advisor.
        yield return Advice
            .For(method)
            .Before(advice =>
            {
                advice.Emit(OpCodes.Ldstr, $"ILGenerator : { method.Name }");
                advice.Emit(OpCodes.Call, Metadata.Method(() => Console.WriteLine(Metadata<string>.Value)));
            });

        //Use simple Action to generate a 'Before' advisor.
        yield return Advice
            .For(method)
            .Before(() => Console.WriteLine($"Action : { method.Name }"));

        //Use an expression to generate an 'After-Returning-Value' Advisor
        yield return Advice
            .For(method)
            .After()
            .Returning()
            .Value(_Execution =>
            {
                return Expression.Call
                (
                    Metadata.Method(() => Console.WriteLine(Metadata<string>.Value)),
                    Expression.Call
                    (
                        Metadata.Method(() => string.Concat(Metadata<string>.Value, Metadata<string>.Value)),
                        Expression.Constant("Returned Value : "),
                        Expression.Call(_Execution.Return, Metadata<object>.Method(_Object => _Object.ToString()))
                    )
                );
            });
        
        //Validate an email parameter value.
        yield return Advice
            .For(method)
            .Parameter<EmailAddressAttribute>()
            .Validate((_Parameter, _Attribute, _Value) =>
            {
                if (_Value == null) { throw new ArgumentNullException(_Parameter.Name); }
                try { new MailAddress(_Value.ToString()); }
                catch (Exception exception) { throw new ArgumentException(_Parameter.Name, exception); }
            });
    }
}

FAQ

  • Can I weave multiple Aspects into the same Pointcut? Yes, just be carefull about weaving order.

  • How can I remove an Aspect from a Pointcut? There is a Release method defined in Aspect to get rid of Aspect from Pointcut.

  • Are attributes required to define Pointcut? No, Pointcut can be defined by directly inherits from Pointcut and implement the abstract method Match that take a MethodBase as single argument and return a boolean to indicate if a method is in Pointcut scope.

  • Why I have to use IPuresharp? Interception is based on IPuresharp. Indeed IPuresharp add a build action to rewrite CIL to make assembly "Architect Friendly" by injecting transparents and hidden features to to grant full execution control at runtime.

  • Can I intercept constructor? If yes, how do I implement it? Constructor interception is supported and is treated like another method with declaring type as first argument and void for return type.

  • Is generic types and methods supported? Generic types and methods ares fully supported by injection.

  • Can I intercept async methods? Async methods ares fully supported by injection and offer a way to intercept each asynchronous steps.

More

Contribution

  • Feedbacks are wellcome, don't hesitate to tell me if any improvements seems to be cool
  • Any pull requests for patching or correct my bad english are wellcome too
  • You can also donate to help financially maintain the project : 3D8txm4gMJDtti7tpcYnndLDfxpADkLggn
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].