• Stars
    star
    283
  • Rank 146,066 (Top 3 %)
  • Language
    C#
  • License
    Apache License 2.0
  • Created about 8 years ago
  • Updated over 4 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

.NET Reflection Made Fast and Simple ⛺

Code Shelter

NuGet

Fasterflect is available on NuGet: https://www.nuget.org/packages/fasterflect/

Overview

If you frequently use .NET Reflection in your application, you would immediately be aware of its two big issues: usability of the API as a whole and performance of reflection invocations (e.g. method invocation or member access). Fasterflect addresses the usability issue by providing intuitive & highly flexible extension methods to Type, Object and various metadata classes (such as FieldInfo, MethodInfo, etc.) which not only preserve but also enhance the .NET Reflection metadata lookup capability. The performance issue of reflection invocation is addressed by Fasterflect through the use of lightweight dynamic code generation, which performs anywhere from 5 to many hundreds times faster than native .NET Reflection invocations.

Fasterflect offers 3 major areas of functionality:

  • Querying: Fasterflect allows you to query .NET metadata, such as looking-up types in an assembly, searching for methods matching a partial name, finding all constructors of a type, etc.
  • Accessing: Fasterflect allows you to perform reflective invocations on constructors, indexers, fields, properties and methods for both reference types (including arrays) and struct types. Fasterflect also supports working with ref/out parameters, inferring parameter types to simplify invocations. These are backed by the dynamic code generation mechanism.
  • Services: Built on top of the core API for querying and accessing, Fasterflect includes several extensions at at higher level of abstraction. This includes functionality for deep object cloning, object materialization (construction) without relying on default constructors, various object mapping scenarios, XML serialization, etc.

Besides being simple, Fasterflect is heavily documented and unit-tested, so you'll find it to be very easy to learn and use. Kickstart your reflection skills by downloading Fasterflect today. We recommend that you start by spending a bit of time with the extensive documentation, but the impatient need only write using Fasterflect;. We also recommend looking at the unit tests in case the documentation proves to be insufficient.

To get a feel of what Fasterflect is like, without first having to download anything or spend time reading the documentation, below is some sample code using Fasterflect to construct objects and access members.

class Person
{
    private int id;
    private int milesTraveled;
    public int Id
    {
        get { return id; }
        set { id = value; }
    }
    public string Name { get; private set; }
    private static int InstanceCount;

    public Person() : this(0) { }

    public Person(int id) : this(id, string.Empty) { }

    public Person(int id, string name)
    {
        Id = id;
        Name = name;
        InstanceCount++;
    }

    public char this[int index]
    {
        get { return Name[index]; }
    }

    private void Walk(int miles)
    {
        milesTraveled += miles;
    }

    private static void IncreaseInstanceCount()
    {
        InstanceCount++;
    }

    private static int GetInstanceCount()
    {
        return InstanceCount;
    }

    public static void Swap(ref int i, ref int j)
    {
        int tmp = i;
        i = j;
        j = tmp;
    }
}

class Program
{
    static void Main()
    {
        var type = Assembly.GetExecutingAssembly().GetType( "FasterflectSample.Person" );
        ExecuteNormalApi(type);
        ExecuteCacheApi(type);
    }

    private static void ExecuteNormalApi(Type type)
    {
        // Person.InstanceCount should be 0 since no instance is created yet
        AssertTrue((int)type.GetFieldValue("InstanceCount") == 0);
        
        // Invokes the no-arg constructor
        object obj = type.CreateInstance();

        // Double-check if the constructor is invoked successfully or not
        AssertTrue(null != obj);

        // Now, Person.InstanceCount should be 1
        AssertTrue(1 == (int)type.GetFieldValue("InstanceCount"));

        // We can bypass the constructor to change the value of Person.InstanceCount directly
        type.SetFieldValue("InstanceCount", 2);
        AssertTrue(2 == (int)type.GetFieldValue("InstanceCount"));

        // Let's invoke Person.IncreaseCounter() static method to increase the counter
        type.CallMethod("IncreaseInstanceCount");
        AssertTrue(3 == (int)type.GetFieldValue("InstanceCount"));

        // Now, let's retrieve Person.InstanceCount via the static method GetInstanceCount
        AssertTrue(3 == (int)type.CallMethod("GetInstanceCount"));

        // Invoke method receiving ref/out params, we need to put arguments in an array
        var arguments = new object[] { 1, 2 };
        type.CallMethod("Swap", 
            // Parameter types must be set to the appropriate ref type
            new[] { typeof(int).MakeByRefType(), typeof(int).MakeByRefType() },
            arguments);
        AssertTrue(2 == (int)arguments[0]);
        AssertTrue(1 == (int)arguments[1]);

        // Now, invoke the 2-arg constructor.  We don't even have to specify parameter types
        // if we know that the arguments are not null (Fasterflect will call arg[n].GetType() internally).
        obj = type.CreateInstance(1, "Doe");

        // id and name should have been set properly
        AssertTrue(1 == (int)obj.GetFieldValue("id"));
        AssertTrue("Doe" == obj.GetPropertyValue("Name").ToString());

        // Let's use the indexer to retrieve the character at index 1
        AssertTrue('o' == (char)obj.GetIndexer(1));

        // If there's null argument, or when we're unsure whether there's a null argument
        // we must explicitly specify the param type array
        obj = type.CreateInstance( new[] { typeof(int), typeof(string) }, 1, null );

        // id and name should have been set properly
        AssertTrue(1 == (int)obj.GetFieldValue("id"));
        AssertTrue(null == obj.GetPropertyValue("Name"));

        // Now, modify the id
        obj.SetFieldValue("id", 2);
        AssertTrue(2 == (int)obj.GetFieldValue("id"));
        AssertTrue(2 == (int)obj.GetPropertyValue("Id"));

        // We can chain calls
        obj.SetFieldValue("id", 3)
           .SetPropertyValue("Name", "Buu");
        AssertTrue(3 == (int)obj.GetPropertyValue("Id"));
        AssertTrue("Buu" == (string)obj.GetPropertyValue("Name"));
         
        // Map a set of properties from a source to a target
        new { Id = 4, Name = "Nguyen" }.MapProperties( obj );
        AssertTrue(4 == (int)obj.GetPropertyValue("Id"));
        AssertTrue("Nguyen" == (string)obj.GetPropertyValue("Name"));

        // Let's have the folk walk 6 miles
	obj.CallMethod("Walk", 6);
		
        // Double-check the current value of the milesTravelled field
        AssertTrue(6 == (int)obj.GetFieldValue("milesTraveled"));

        // Construct an array of 10 elements for current type
        var arr = type.MakeArrayType().CreateInstance(10);

        // GetValue & set element of array
        obj = type.CreateInstance();
        arr.SetElement(4, obj)
           .SetElement(9, obj);

        AssertTrue(obj == arr.GetElement(4));
        AssertTrue(obj == arr.GetElement(9));
        AssertTrue(null == arr.GetElement(0));
    }

    private static void ExecuteCacheApi(Type type)
    {
        var range = Enumerable.Range(0, 10).ToList();

        // Let's cache the getter for InstanceCount
        StaticMemberGetter count = type.DelegateForGetStaticFieldValue("InstanceCount");

        // Now cache the 2-arg constructor of Person and playaround with the delegate returned
        int currentInstanceCount = (int)count();
        ConstructorInvoker ctor = type.DelegateForCreateInstance(new[] { typeof(int), typeof(string) });
        range.ForEach(i =>
        {
            object obj = ctor(i, "_" + i);
            AssertTrue(++currentInstanceCount == (int)count());
            AssertTrue(i == (int)obj.GetFieldValue("id"));
            AssertTrue("_" + i == obj.GetPropertyValue("Name").ToString());
        });

        // Getter/setter
        MemberSetter nameSetter = type.DelegateForSetPropertyValue("Name");
        MemberGetter nameGetter = type.DelegateForGetPropertyValue("Name");

        object person = ctor(1, "John");
        AssertTrue("John" == (string)nameGetter(person));
        nameSetter(person, "Jane");
        AssertTrue("Jane" == (string)nameGetter(person));

        // Invoke method
        person = type.CreateInstance();
        MethodInvoker walk = type.DelegateForCallMethod("Walk", new[] { typeof(int) });
        range.ForEach(i => walk(person, i));
        AssertTrue(range.Sum() == (int)person.GetFieldValue("milesTraveled"));
        
        // Map properties
        var ano = new { Id = 4, Name = "Doe" };
        var mapper = ano.GetType().DelegateForMap( type );
        mapper(ano, person);
        AssertTrue(4 == (int)person.GetPropertyValue("Id"));
        AssertTrue("Doe" == (string)person.GetPropertyValue("Name"));

    }

    public static void AssertTrue(bool expression)
    {
        if (!expression)
            throw new Exception("Not true");
        Console.WriteLine("Ok!");
    }
}

Copyright

Copyright 2010 Buu Nguyen, Morten Mertner

More Repositories

1

mongoose-deep-populate

Mongoose plugin to enable deep population of nested models ⛺
JavaScript
469
star
2

topbar

Tiny & beautiful site-wide progress indicator
CSS
436
star
3

redux-freeze

Redux middleware that prevents state from being mutated anywhere in the app
JavaScript
213
star
4

combres

ASP.NET and MVC performance optimization library ⛺
C#
123
star
5

route-decorators

ES7 decorators that simplify Koa and Express route creation
JavaScript
75
star
6

esql

Humane query language for Elasticsearch ⛺
JavaScript
50
star
7

memento

Lightweight and extensible undo framework for .NET ⛺
C#
33
star
8

bike

Cross-platform, CLR-based programming language
C#
29
star
9

exif-orient

Library to orient images based on their Exif orientation ⛺
JavaScript
21
star
10

koa-req-validator

Declarative request validation middleware for Koa
JavaScript
19
star
11

redux-validate-fsa

Redux middleware that validates if an action is a Flux Standard Action (FSA).
JavaScript
16
star
12

notify

Change tracking library for .NET ⛺
C#
13
star
13

jundo

JavaScript Undo Library ⛺
JavaScript
11
star
14

jcr

jQuery Carousel ⛺
HTML
7
star
15

cordova-photo-library

Cordova plugin to save images and videos to photo library ⛺
Objective-C
5
star
16

misc-js

Miscellaneous JavaScript
JavaScript
4
star
17

local-server

Minimal static server
JavaScript
3
star
18

spotify-importer

Import local music library to Spotify
JavaScript
3
star
19

evtify

Event emitter for Node & browser ⛺
JavaScript
2
star
20

grunt-mindirect

Grunt task to perform in-place JS minification
JavaScript
1
star
21

metronome

Simple metronome
HTML
1
star
22

qtrace-samples

Sample code for qTrace publishers
C#
1
star