Coder Social home page Coder Social logo

puresharper / cneptune Goto Github PK

View Code? Open in Web Editor NEW
31.0 5.0 7.0 56 KB

CNeptune improve productivity & efficiency by urbanize .net module with meta-code to lay foundation for frameworks

License: MIT License

C# 100.00%
architecture aop interception pattern design mock injection cil mocking dependency

cneptune's Introduction

NuGet

CNeptune

CNeptune is an util based on mono.cecil to rewrite .net assembly to inject all the needs to control execution flow in order to help architects to build a productive and efficient architecture.

Features

  • Dynamic : change method behavior at runtime
  • Efficient : injected mechanism is extremely efficient
  • Limitless : support all type of methods (constructors included)
  • Transparent : client side perception is not affected

Coverage

  • Aspect-Oriented Programming
  • Code contract / Data validation
  • Uncoupling technical concern
  • Diagnostics & measures
  • Mocking & tests
  • Simplify existing design pattern

Example of injection

  • Rewrite .net assembly by specifying path
neptune.exe "C:\...\Assembly.dll"
  • Rewrite .net assembly by specifying project and configuration
neptune.exe "C:\...\Project.csproj" "Debug"
PM> Install-Package CNeptune

Example of usage

  • Override method at runtime

Business

public class Calculator
{
    public int Add(int a, int b)
    {
        return a + b;
    }
}

Obtain the delegate to manage a method of 'Calculator'

var _update = typeof(Calculator).GetNestedType("<Neptune>", BindingFlags.NonPublic).GetField("<Update>").GetValue(null) as Action<MethodBase, Func<MethodInfo, MethodInfo>>;

Define 'Add' method to inject a console 'Hello World' before call.

_update
(
    typeof(Calculator).GetMethod("Add"),
    _Method =>
    {
        var _method = new DynamicMethod(string.Empty, typeof(int), new Type[] { typeof(Calculator), typeof(int), typeof(int) }, typeof(Calculator), true);
        var _body = _method.GetILGenerator();
        _body.EmitWriteLine("Hello World");
        _body.Emit(OpCodes.Ldarg_0); //this
        _body.Emit(OpCodes.Ldarg_1); //a
        _body.Emit(OpCodes.Ldarg_2); //b
        _body.Emit(OpCodes.Call, _Method);
        _body.Emit(OpCodes.Ret);
        return _method;
    }
);

cneptune's People

Contributors

puresharper 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

Watchers

 avatar  avatar  avatar  avatar  avatar

cneptune's Issues

3rd party assembly injection error

If I try to run something like this from the cmd:

CNeptune.exe "C:\...\bin\Debug\Newtonsoft.Json.dll" "Release"

I get:

Unhandled Exception: System.Xml.XmlException: Data at the root level is invalid. Line 1, position 1.
   at System.Xml.XmlTextReaderImpl.Throw(Exception e)
   at System.Xml.XmlTextReaderImpl.ParseRootLevelWhitespace()
   at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
   at System.Xml.Linq.XDocument.Load(XmlReader reader, LoadOptions options)
   at System.Xml.Linq.XDocument.Load(String uri, LoadOptions options)
   at CNeptune.Program.Main(String[] arguments)

There must be something I'm missing, but it is not obvious to me.

Error on build due to not default package folder

Hi

I've got an exception when building due to the fact that my packages folder is not in the default location.
it tries to use Foundation\Data\packages\CNeptune.1.2.1\build\CNeptune.exe whereas the package folder can be found under packages\CNeptune.1.2.1\build\CNeptune.exe (it's a rootfolder for all projects and solutions).

Is there a possibility to adapt this that i lookt to the nuget.config repositorypath instead of the default path?

Roadmap

Interception

Virtual method : change virtual interception to match with virtual pattern and always wrap entire virtual call (in progress)

public class A
{
    virtual public void Method()
    {
        Console.WriteLine("A");
    }
}

public class B : A
{
    override public void Method()
    {
        Console.WriteLine("B");
        base.Method();
    }
}

Without tweak, calling 'B.Method()' will produce

B
A

If 'A.Method()' is replaced by a method that call 'Console.WrireLine("C")' before original code, it will produce

B
C
A

The virtual pattern should produce

C
B
A

Generic method : change generic interception to wrap generic definition call into parameterized generic call.

public class A
{
    public void Method<T>()
    {
        Console.WriteLine("A");
    }
}

Without tweak it will produce when calling 'A.Method()'

A

If 'A.Method()' is replaced by a method that call Console.WriteLine("B") before original code, it will produce

B
A

If 'A.Method<>()' is replaced by a method that call 'Console.WriteLine("C")' before original code, it will produce

B
A

It is explain by 'A.Method()' make the last decision.
Respecting generic method definition should produce

B
C
A

Helper

  • high speed static method to create and uninitialized inetance of non abstract class.
  • high speed serialization/deserialization template
  • external virtual dispatch using visitor pattern

Usage

  • method registration : a nested class contains a pointer for redirection with default pointer on original code and need a method to help to convert methodinfo to pointer. (done)
  • generic method definition registration : parameterized/closed generic methods are treated like non generic method but in some case it can be good to register directly the generic method definition.
  • add a way to get the methodinfo that execute user code from visible method. (in progress)
  • list all injected methods

Integration

  • Create the associated nuget package (done)
  • Make rewriter idempotent (done)
  • Detect real assembly extension to support .exe (done)

Administration

  • Create an administration nuget package
  • Interface for direct usage
  • Additional explicit interfaces
  • Additional private fields
  • Modules & Classes trigger?

CNeptune masks exceptions

When running an Altova MapForce mapping, expecting XML input, on a non-XML, the following exception is emitted:

   at System.Xml.XmlTextReaderImpl.Throw(Exception e)
   at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
   at System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean preserveWhitespace)
   at System.Xml.XmlDocument.Load(XmlReader reader)
   at System.Xml.XmlDocument.Load(String filename)
   at Altova.Xml.XmlTreeOperations.LoadDocument(String filename)
   at Altova.Xml.XmlTreeOperations.LoadDocument(Input input)
   at MyMapping.seq4_if_is_filename_with_wildcard.Enumerator.MoveNext()
   at Altova.Functions.Core.SequenceCache.fillCache(SequenceCache sc)
   at Altova.Functions.Core.SequenceCache.Enumerator.MoveNext()
   at MyMapping.seq10_filter.Enumerator.MoveNext()
   at MyMapping.seq9_join.Enumerator.MoveNext()
   at Altova.Mapforce.MFNodeByKindFilter.Enumerator.MoveNext()
   at Altova.Mapforce.MFDomWriter.Write(IEnumerable what, XmlNode where)
   at Altova.Mapforce.MFDomWriter.Write(IEnumerable what, XmlNode where)
   at MyMapping.Run(Object OutputFilenameSourceParameter, Object InputFilenameSourceParameter)
   at Esxml2_to_Esxml2.Esxml2_to_Esxml2Console.Main(String[] args)

If CNeptune is added to the the generated Altova project build - without making any use of it such as NConcern aspects - the exception is silently masked (output is an empty XML file).

Error in first build.

I wanted to try NConcern and create a simple console application that lists folder content. But this error occured.
The command ""C:\Users\f\Documents\Visual Studio 2015\Projects\FolderList\packages\CNeptune.1.1.0\build\CNeptune.exe" "C:\Users\f\Documents\Visual Studio 2015\Projects\FolderList\FolderList\FolderList.csproj" "Debug"" exited with code -532462766

Problem with BadImageFormatException when instantiating generic class referencing ObservableCollection

The following code will reproduce the problem
Using CNeptune version 1.2.1

namespace NConcernConstructorFail
{
    class Program
    {
        static void Main(string[] args)
        {
            var a = new A(); // OK
            var b = new B<int>(); // System.BadImageFormatException: 'An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)'
        }
    }
    class A
    {
        ObservableCollection<int> o = new ObservableCollection<int>();
    }
    class B<T>
    {
        ObservableCollection<T> o = new ObservableCollection<T>();
    }
}

bug: debuginfo not handled correctly

Hi again thanks for fast response time

I have run in to another problem, this time with the debugger

  1. when I select Switch to Frame in the call stack in the the weaved assembly, the debugger select the wrong code, usual the line before the correct line
  2. for some lines in the weaved assembly it is not possible to set a break point

The methods in questions are in the weaved assembly they are not adviced though (the pattern delegate returned false for those methods)

Parsing large delegates fails.

Hi it's me again.

I created a simple test assembly and managed to break the project.

using System;

namespace CNeptuneSample
{
    internal static class Program
    {
        private static int Main(string[] args)
        {
            Console.Out.WriteLine(new Sample().Sum(16, 6));
            Console.In.ReadLine();

            return 0;
        }
    }

    public class Sample
    {
        public float Sum(float a, float b)
        {
            return a + b;
        }
    }

    public delegate TResult Func<T1, TResult>(T1 arg1);

    // Above part works flawlessly, but this delegate brakes the system
    public delegate TResult Func<T1, T2, T3, T4, T5, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
}

Exception that is thrown (see comment in code):

System.ArgumentOutOfRangeException was unhandled
  HResult=-2146233086
  Message=Specified argument was out of the range of valid values.
  Source=Mono.Cecil
  StackTrace:
       w Mono.Collections.Generic.Collection`1.get_Item(Int32 index)
       w CNeptune.Program.Manage(TypeDefinition gateway, TypeDefinition authentic, FieldDefinition authority, MethodDefinition method) w C:\Development\Source\Tests\CNeptune-master\CNeptune\CNeptune\Program.cs:wiersz 215
       w CNeptune.Program.Manage(TypeDefinition gateway, TypeDefinition authentic) w C:\Development\Source\Tests\CNeptune-master\CNeptune\CNeptune\Program.cs:wiersz 89
       w CNeptune.Program.Manage(String assembly) w C:\Development\Source\Tests\CNeptune-master\CNeptune\CNeptune\Program.cs:wiersz 69
       w CNeptune.Program.Main(String[] arguments) w C:\Development\Source\Tests\CNeptune-master\CNeptune\CNeptune\Program.cs:wiersz 25
  InnerException: 

I will try to find more examples that breaks this approach.

Btw. This lib is better than obfuscation. dnSpy can't locate original code anywhere :D

Cheers


Edit: Unlocalize message in exception.

Feature request proper handling of abstract methods

Due to issue #5 I move my code to a library, for some reason I had to manual update the project with Import CNeptune etc. I copied what was previous in the WinExe project file.
Now I get another runtime exception:
Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
LoaderExceptions are:
Could not load type '<Neptune>' from assembly 'Outliner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' because the method '<get_Start>' has no implementation (no RVA).
and
Could not load type '<Neptune>' from assembly 'Outliner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' because the method '<get_Name>' has no implementation (no RVA).
where Start is an abstract protected property to be weaved
and Name is an abstract public properties not to be weaved (changing them to public did not help)
my weaver code looks like this:
Aspect.Weave<ParserAspect>(methodBase => { if (methodBase.IsAbstract) return false; if (!typeof(Parser).IsAssignableFrom(methodBase.DeclaringType)) return false; var methodInfo = methodBase as MethodInfo; if (methodInfo == null) return false; if (!typeof(Term).IsAssignableFrom(methodInfo.ReturnType)) return false; Debug.WriteLine($"Weave {methodBase.DeclaringType}.{methodBase.Name}"); return true; });
the exception happens before the pattern lambda has a chance to test IsAbstract and abort weaving of the method
changing the properties from abstract to virtual fix the problem

PS. I use NConcept to specify the weaving, VS2017 and is targeting .NET 4.5.2 framework

Exception after updating to CNeptune 1.1.0

2>------ Build started: Project: Outliner, Configuration: Debug Any CPU ------
2> Outliner -> C:\Users\xx\Documents\Visual Studio 2017\Projects\yy\Outliner\bin\Debug\Outliner.dll
2>
2> Unhandled Exception: System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
2> at Mono.Collections.Generic.Collection`1.get_Item(Int32 index)
2> at CNeptune.Program.Manage(MethodDefinition method)
2> at CNeptune.Program.Manage(TypeDefinition type)
2> at CNeptune.Program.Manage(String assembly)
2> at CNeptune.Program.Main(String[] arguments)
2>C:\Users\xx\Documents\Visual Studio 2017\Projects\yy\packages\CNeptune.1.1.0\build\CNeptune.targets(10,9): error MSB3073: The command ""C:\Users\xx\Documents\Visual Studio 2017\Projects\yy\packages\CNeptune.1.1.0\build\CNeptune.exe" "C:\Users\xx\Documents\Visual Studio 2017\Projects\yy\Outliner\Outliner.csproj" "Debug"" exited with code -532462766.

Outliner.csproj OutputType = Library

breaking System.Linq.Enumarable

My code stops working with CNeptune installed via nuget, because the System.Linq.Enumarable Extension methods (FirstOrDefault() in my case) are no more available on runtime.

Feedback

Hi,

You can suggest here a change, expose a need or comment something.
I am always happy to read good or bad opinions because they help me to improve what I produce and myself at the same time. So do not hesitate :)

CNeptune silently breaks my application

Hi,

I encountered a weird behaviour using CNeptune as requirement to NConcern. I have an application that reads data from the serial port. After adding NConcern and CNeptune via NuGet to VisualStudio and weaving logging aspects into my application the listener for data from the serial port gets not called anymore.
Uncommenting the weaving code did not help.
BUT: After removing CNeptune via NuGet everything works fine again.
I did this a few times (add and remove CNeptune, commenting out the weaving, etc.) to be shure that it's nothing else. However the behaviour stays the same.
Is this a known behaviour?

Cheers,
Frank

Analytical anomaly

/// <summary> /// 泛型单例 /// </summary> /// <typeparam name="T"></typeparam> public abstract class BaseInstance<T> where T : class,new() { private readonly static object lockObj = new object(); private static T instance = null; protected bool IsConnect = false; public static T Instance { get { if (instance == null) { lock (lockObj) { if (instance == null) { instance = new T(); } } } return instance; } } } public class Testclass : BaseInstance<Testclass> { [OperationContract] public void Test(string a) { //return 3; } }

Demo code:
static void Main(string[] args)
{
//define a joinpoint
var _operationContractJoinpoint = new Func<MethodBase, bool>(_Method => _Method.IsDefined(typeof(OperationContractAttribute), true));

        //instantiate a calculator
        var _calculator = new Calculator();

        //weave logging for all operation contract
        Aspect.Weave<Logging>(_operationContractJoinpoint);

        //invoke an operation contract (logging is enabled)
        var _return = _calculator.Divide(15, 3);
        Testclass.Instance.Test("test");
     }

The .Net Reflector Analytical anomaly and NConcern.Example.Basic Demo Exception:

在 System.Signature.GetSignature(Void* pCorSig, Int32 cCorSig, RuntimeFieldHandleInternal fieldHandle, IRuntimeMethodInfo methodHandle, RuntimeType declaringType)
在 System.Reflection.RuntimeMethodInfo.FetchNonReturnParameters()
在 System.Reflection.RuntimeMethodInfo.GetParameters()
在 System.Diagnostics.StackTrace.ToString

.net standard support

There are many projects with .net standard. So it will be great to support it in the nuget.

Request: support for OutputType=WinExe

Got the following exception:
Unhandled Exception: System.NotSupportedException: Specified method is not supported. at CNeptune.Instrumentation.Program.Main(String[] arguments) C:\Users\xx\Documents\Visual Studio 2017\Projects\...\packages\CNeptune.1.0.5\build\CNeptune.targets(10,9): error MSB3073: The command ""C:\Users\xx\Documents\Visual Studio 2017\Projects\...\packages\CNeptune.1.0.5\build\CNeptune.exe" "C:\Users\xx\Documents\Visual Studio 2017\Projects\...\WindowsFormsApplication1\WindowsFormsApplication1.csproj" "Debug"" exited with code -532462766.

May I also suggest that you add the following message to NotSupportedException: $"Unknown OutputType: {_type.Value}"

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.