Geranium.Reflection 2.0.1

There is a newer version of this package available.
See the version list below for details.
dotnet add package Geranium.Reflection --version 2.0.1
NuGet\Install-Package Geranium.Reflection -Version 2.0.1
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Geranium.Reflection" Version="2.0.1" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Geranium.Reflection --version 2.0.1
#r "nuget: Geranium.Reflection, 2.0.1"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Geranium.Reflection as a Cake Addin
#addin nuget:?package=Geranium.Reflection&version=2.0.1

// Install Geranium.Reflection as a Cake Tool
#tool nuget:?package=Geranium.Reflection&version=2.0.1

Geranium.Reflection

NuGet version

.NET reflection provided by ExpressionTrees. An alternative for reflection by extensions methods based on Expressions. This extensions allow create new instances without activator, set or get property values of unknown types and unknown properties, check equality with unknown type default value, call object methods and extension methods avoiding Invoke, and couple of non-expression extensions for as/is.

Benchmarks

Benchmarks resuts

  • New() average faster then Activator in 10 times
  • GetPropValue() average faster then PropertyInfo in 2 times
  • SetPropValue() average faster then PropertyInfo in 2 times

Short list of features:

  • New
  • get/set
  • default
  • is
  • as
  • call

Supported targets:

  • net6.0+
  • netcoreapp3.1+
  • netstandard2.1+
  • net46+

New

Alternative for Activator.CreateInstance provided by Expression.New lambda cached by System.Type into Delegate.

Available methods

  • T New<T>(this object)
  • T New<T>(this object, object[] ctorArgs)
  • T New<T>(this object, ConstructorInfo ctor, params object[] ctorArgs) - main
  • object New(this object)
  • object New(this object, object[] ctorArgs)
  • object New(this object, bool oblyParameterless, object[] ctorArgs) - FirstOrDefault ctor

Examples

Getting List<T> as IList of Type in runtime:

public static IList IList(this Type type)
{
    return typeof(List<>).MakeGenericType(type)
        .New()
        .As<IList>();
}

Create and apply migration from migration type:

void RunMigration(Type migrationType)
{
    var migration = migrationType.NewAs<CodegenMigration>();
    ...
    migration.Apply();
    ...
}

Get property / Set property

Get property values:

There is basic method for getting value from property based on Expression.PropertyOrField:

  • GetPropertyExprRaw(this object, string propertyName)

And two overloads:

  • GetPropertyExpr<TValue>(this object, string propertyName)
  • GetStaticProperty(this Type, string propertyName)

Example of getting 'Id' value of uknown type:

var rowAccess = new RowAccess
{
    Type = typeof(T),
    IdValue = entity.GetPropertyExprRaw("Id") // value can be long/string/Guid or something
};

Set property values:

There is couple of methods setting value or property: type-known - when you know type of property, and 'converted' - when value and property can be different types:

  • SetPropertyExprType(this @object, string propName, object propValue, Type valueType)
  • SetPropertyExprConverted(this object @object, string propName, object propValue)

'Converted' trying to convert value to property type, by:

  • if nullable, Expressions too hard to predict, so: prop.SetValue
  • if IsEnum, Enum.Parse(value.ToString())
  • in other cases, Convert.ChangeType

After converting, using 'main' method SetPropertyExprType, which set value by Delegate compiled by expressions based on Expression.Assign.

Example method of setting 'Id' value when you don't know type:

public static void SetId<TId>(this object obj, TId value) 
=> obj.SetPropertyExprConverted("Id", value);

public static void SetId(this object obj, object value) 
=> obj.SetPropertyExprConverted("Id", value);

Example of create IList and bind to object:

var type = obj.GetType();
var prop = type.GetProperty('Users');
var list = prop.IList();
obj.SetPropertyExprConverted(prop.Name, list);

Default

Alternative of default for System.Type in runtime based on Expression.Default() with cache available by DefaultExtensions.Default(this Type type):

var type = obj.GetType();
var prop = type.GetProperty('Id');
var value = prop.GetValue(obj);
if(value.Equals(type.Default())
    Console.WriteLine("Property is not initialized!");

Extensions provided not by ExpressionTree

Equivalent of C# 'as'

  • As<T>(this object)
  • As<T>(this object, bool throw)
  • As<T>(this object, T default)

Equivalent of C# 'is/not' check

  • Is<T>(this object)
  • Is<T>(this object, out T match)
  • IsNot<T>(this object)
  • IsNot<T>(this object, out T match)
  • Is<T>(this Type)
  • Is<T>(this Type, out T match)
  • IsNot<T>(this Type)
  • IsNot<T>(this Type, out T match)

Additional methods for 'is something'

  • IsSimple
  • IsPrimitive
  • IsNumericType
  • IsDateType
  • IsNullable
  • IsNullablePrimitive
  • IsAnonymousType
  • IsICollection
  • IsDbCollection

Additional methods for IEnumerable

'String' checks differenlty

  • IsEmpty
  • IsNotEmpty

Call

Extensions for call methods by ExpressionTrees Available methods for 'call':

  • obj.Call("Equalls",null);
  • dbCtx.CallGeneric("Set",new Type[]{ typeof(User) });
  • typeof(Console).CallStatic("WriteLine", "log");
  • list.CallExtension("ToList",typeof("EnumerableExtensions");

Overloads for call static generic, call generic extension, Call with T result etc included.

Example of using Call chain with LiteDatabase: gettin anonymous class from store in runtime:


var liteDbCollectionQueryable = LiteDb
    .CallGeneric("GetCollection", new Type[] { type })
    .Call("FindAll")
    .CallGenericExtension("ToList", typeof(Enumerable), new[] { type })
    .CallGenericExtension("AsQueryable", typeof(Queryable), new[] { type });
    
var filtered = SelectionModelConverter
    .CallGeneric("Convert", new Type[] { type }, selection, liteDbCollectionQueryable)
    .GetPropertyExprRaw("Result");
    
var (filteredPropertyConverted, anonymousType) = SelectionModelConverter
    .CallGeneric<(IQueryable, Type)>("ConvertProperties", new Type[] { type }, selection.Properties, filtered); // returns IQueryable and anonymousType
    
var materialize = filteredPropertyConverted.CallGenericExtension("ToList", typeof(Enumerable), new[] { anonymousType });

TypeFromAssemblyExtensions

Extensions for getting Types and instances of Type from Assembly and assembly names loaded from AppDomain.Current.BasePath.

Note about performance (package version 1.0.0)

That's not speed-up alternative. You can check it by run some benchmarks. That's alternative of System.Reflection. With .NET6 all techniques of 'speed-up' by ExpressionTrees and even source generators is pointless because of reflection improvements described here: https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-6/#reflection But still it can be useful alternative for full .NET Framework with 'old' runtime.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 is compatible. 
.NET Standard netstandard2.1 is compatible. 
.NET Framework net46 is compatible.  net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETCoreApp 3.1

    • No dependencies.
  • .NETFramework 4.6

    • No dependencies.
  • .NETStandard 2.1

    • No dependencies.
  • net6.0

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Geranium.Reflection:

Package Downloads
Geranium.Modules

Modules

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
2.1.2 648 8/25/2023
2.0.2 839 6/13/2023
2.0.1 415 5/8/2023
1.0.0 154 4/21/2023