DynamicBinder 2.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package DynamicBinder --version 2.0.0
NuGet\Install-Package DynamicBinder -Version 2.0.0
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="DynamicBinder" Version="2.0.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add DynamicBinder --version 2.0.0
#r "nuget: DynamicBinder, 2.0.0"
#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 DynamicBinder as a Cake Addin
#addin nuget:?package=DynamicBinder&version=2.0.0

// Install DynamicBinder as a Cake Tool
#tool nuget:?package=DynamicBinder&version=2.0.0

DynamicBinder and LateBinder NuGet Package

What's this?

This is the class library for .NET.

This library allows you dynamic access to object methods, properties, and fields by using the reflection technology of .NET, regardless of whether they are private members.

You can access both object instance members and class static members by name that specified string argument at runtime, not compile-time, or C# 4.0 "dynamic" syntax.

How to install?

You can install this library via NuGet.

PM> Install-Package DynamicBinder

Usage - C# "dynamic" syntax

Create instance

After importing (opening) namespace Toolbelt, you can use DynamicBinder.CreateInstance<T>(...) and DynamicBinder.CreateInstance(Type t, ...) static method to instantiate any objects with any constructors, regardless of constructor's access level (public, internal, protected, private).

Those methods return an instantiated object wrapped with the DynamicBinder object as a dynamic type.

using Toolbelt;
...
// 👇 The type of the "dynamicObj" is the "dynamic" type.
//    In this case, the "dynamicObj" is instantiated by the constructor, which has two arguments.
//    It can be instantiated even if the constructor is private.
var dynamicObj = DynamicBinder.CreateInstance<MyClass>(arg1, arg2);

// And it can be invoked its instance methods, regardless of its access level.
var retval = (int)dynamicObj.PrivateMethodName(arg3, arg4);
...

Access to instance members

After importing (opening) namespace Toolbelt.DynamicBinderExtension, you can use ToDynamic() extension method that returned C #4.0 dynamic type at any object.

using Toolbelt.DynamicBinderExtension;
...
var obj = new MyClass();
...
// call instance method.
var retval = (int)obj.ToDynamic().MethodName(arg1, arg2);

// get & set instance property.
var value = (int)obj.ToDynamic().PropName;
obj.ToDynamic().PropName = newValue;

// get & set instance field.
var value = (int)obj.ToDynamic().FieldName;
obj.ToDynamic().FieldName = newValue;

Access to static members

After importing (opening) namespace Toolbelt, you can use DynamicBinder.Create<T>() and DynamicBinder.Create(Type t) static method that returned C #4.0 dynamic type.

using Toolbelt;
...
var binder = DynamicBinder.Create(typeof(Foo));
// call static method.
var retval = (int)binder.MethodName(arg1, arg2);

// get & set static property.
var value = (int)binder.PropName;
binder.PropName = newValue;

// get & set static field.
var value = (int)binder.FieldName;
binder.FieldName = newValue;

Notice: retrieve class type return value from method calling

The following test code will be failed.

object bar = foo.ToDynamic().GetBarObject();

// 👇 It will be reported "actual is `DynamicBinder`" !
Assert.AreEqual("BarClass", bar.GetType().Name); 

You should rewrite avobe test code as follow.

// Extract C# dynamic object to `DynamicBinder` object by `as` casting.
var retval = foo.ToDynamic().GetBarObject() as DynamicBinder;

// `DynamicBinder` class exposes the `Object` property to access the binding target object.
Assert.AreEqual("BarClass", retval.Object.GetType().Name); // Green. Pass!

Of course, if you have the right type information, those test codes can be rewritten as the following:

var bar = (BarClass)foo.ToDynamic().GetBarObject();
Assert.AreEqual("BarClass", bar.GetType().Name); // Green. Pass!

Usage - Late bind syntax

Create instance

After importing (opening) namespace Toolbelt, you can use LateBinder.CreateInstance<T>(...) and LateBinder.CreateInstance(Type t, ...) static method to instantiate any objects with any constructors, regardless of constructor's access level (public, internal, protected, private).

Those methods return an instantiated object wrapped with the LateBinder type.

using Toolbelt;
...
// 👇 The type of the "dynamicObj" is the "LateBinder" type.
//    In this case, the "dynamicObj" is instantiated by the constructor, which has two arguments.
//    It can be instantiated even if the constructor is private.
var dynamicObj = LateBinder.CreateInstance<MyClass>(arg1, arg2);

// And it can be invoked its instance methods, regardless of its access level.
var retval = (int)dynamicObj.Call("PrivateMethodName", arg3, arg4);
...

Access to instance members

After importing (opening) namespace Toolbelt.DynamicBinderExtension, you can use ToLateBind() extension method that returned LateBinder object at any object.

LateBinder has follow members.


  • Call(name, params[] args) method
  • Prop[name] property
  • Field[name] property

using Toolbelt.DynamicBinderExtension;
...
// call method.
var retval = (int)obj.ToLateBind().Call("MethodName", arg1, arg2);

// get & set property.
var value = (int)obj.ToLateBind().Prop["PropName"];
obj.ToLateBind().Prop["PropName"] = newValue;

// get & set field.
var value = (int)obj.ToLateBind().Field["FieldName"];
obj.ToLateBind().Field["FieldName"] = newValue;

Access to static members

After importing (opening) namespace Toolbelt, you can use LateBinder.Create<T>() and LateBinder.Create(Type t) static method that returned LateBinder object.

using Toolbelt;
...
var binder = LateBinder.Create<Foo>();
// call static method.
var retval = (int)binder.Call("MethodName", arg1, arg2);

// get & set static property.
var value = (int)binder.Prop["PropName"];
binder.Prop["PropName"] = newValue;

// get & set static field.
var value = (int)binder.Field["FieldName"];
binder.Field["FieldName"] = newValue;

Note

No using extension methods scenario

If you feel these extension methods are dirty, you can choose no using these extension methods.

Instead, you can use LateBinder and DynamicBinder class like the following code.

// Do not open namespace "Toolbelt.DynamicBinderExtension".
using Toolbelt;
...
// Instead, instantiate DynamicBinder or LateBinder objects with the "new" keyword.
dynamic dynamicBinder = new DynamicBinder(obj);
var retval = (int)dynamicBinder.MethodName(arg1, arg2);

var lateBinder = new LateBinder(obj);
var retval = (int)lateBinder.Call("MethodName", arg1, arg2);

"Reinventing the wheel"

There are no less than 50 packages about reflection & private members accessing.

But I couldn't find any packages with my favorite syntax and features 😃.

So I decided to "reinvent the wheel" by my hand.

Performance issue

In this library, DynamicBinder and LateBinder may be much slower because their implementation uses the reflection API directory without any technics such as caches, compiling to delegations, compiling to expressions, etc.

Therefore, I think there is plenty of room for improvement to faster, more high performance.

If you prefer, you can fork this repository and improve it.

Release Notes

Release notes are here.

Licence

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  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 netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework 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 tizen40 was computed.  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.
  • .NETStandard 2.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories (1)

Showing the top 1 popular GitHub repositories that depend on DynamicBinder:

Repository Stars
jsakamoto/Toolbelt.Blazor.I18nText
The class library that provides the ability to localize texts on your Blazor app!
Version Downloads Last updated
2.2.0 320 12/31/2023
2.1.0 78 12/28/2023
2.0.0 3,158 3/28/2022
1.5.1 5,060 12/22/2017
1.5.0 19,749 4/22/2014
1.4.0 1,381 4/18/2014
1.3.0 1,219 3/14/2014
1.2.0 1,239 3/12/2014
1.1.0 1,220 3/1/2014
1.0.0 1,345 2/22/2014

v.2.0.0
- Enhance: Add DynamicBinder.CreateInstance() and LateBinder.CreateInstance().
- Drop support for old .NET Framework versions.