{"id":20409378,"url":"https://github.com/jsakamoto/dynamicbinder","last_synced_at":"2025-04-12T15:45:03.210Z","repository":{"id":14374735,"uuid":"17084761","full_name":"jsakamoto/dynamicbinder","owner":"jsakamoto","description":"C# dynamic access to methods, properties, and fields even if they are private members, powered by Reflection technology.","archived":false,"fork":false,"pushed_at":"2023-12-31T04:11:24.000Z","size":533,"stargazers_count":14,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-26T10:11:36.204Z","etag":null,"topics":["csharp","dynamic","late-binding","private-access","reflection"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jsakamoto.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-02-22T12:54:59.000Z","updated_at":"2024-07-14T09:03:04.000Z","dependencies_parsed_at":"2024-11-15T12:16:35.453Z","dependency_job_id":null,"html_url":"https://github.com/jsakamoto/dynamicbinder","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsakamoto%2Fdynamicbinder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsakamoto%2Fdynamicbinder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsakamoto%2Fdynamicbinder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsakamoto%2Fdynamicbinder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jsakamoto","download_url":"https://codeload.github.com/jsakamoto/dynamicbinder/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248591046,"owners_count":21129948,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csharp","dynamic","late-binding","private-access","reflection"],"created_at":"2024-11-15T05:41:16.986Z","updated_at":"2025-04-12T15:45:03.172Z","avatar_url":"https://github.com/jsakamoto.png","language":"C#","readme":"﻿# DynamicBinder and LateBinder [![NuGet Package](https://img.shields.io/nuget/v/DynamicBinder.svg)](https://www.nuget.org/packages/DynamicBinder/) [![unit tests](https://github.com/jsakamoto/dynamicbinder/actions/workflows/unit-tests.yml/badge.svg)](https://github.com/jsakamoto/dynamicbinder/actions/workflows/unit-tests.yml)\n\n## What's this?\n\nThis is the class library for .NET.\n\nThis library allows you dynamic access to object methods, properties, and fields using the reflection technology of .NET, regardless of whether they are private members.\n\nYou can access both objects' instance members and classes' static members by name that specified string argument at runtime, not compile-time, or C# 4.0 \"dynamic\" syntax.\n\n## How to install?\n\nYou can install this library via [NuGet](https://www.nuget.org/packages/DynamicBinder/).\n\n```shell\n\u003e dotnet add package DynamicBinder\n```\n\n## Usage - C# \"dynamic\" syntax\n\n### Create instance\n\nAfter importing (opening) namespace `Toolbelt`, you can use `DynamicBinder.CreateInstance\u003cT\u003e(...)` and `DynamicBinder.CreateInstance(Type t, ...)` static method to instantiate any objects with any constructors, regardless of constructor's access level (public, internal, protected, private).\n\nThose methods return an instantiated object wrapped with the `DynamicBinder` object as a `dynamic` type.\n\n```csharp\nusing Toolbelt;\n...\n// 👇 The type of the \"dynamicObj\" is the \"dynamic\" type.\n//    In this case, the \"dynamicObj\" is instantiated by the constructor, which has two arguments.\n//    It can be instantiated even if the constructor is private.\nvar dynamicObj = DynamicBinder.CreateInstance\u003cMyClass\u003e(arg1, arg2);\n\n// And it can be invoked its instance methods, regardless of its access level.\nvar retval = (int)dynamicObj.PrivateMethodName(arg3, arg4);\n...\n```\n\n### Access to instance members\n\nAfter importing (opening) namespace `Toolbelt.DynamicBinderExtension`, you can use `ToDynamic()` extension method that returned C #4.0 `dynamic` type at any object.\n\n```csharp\nusing Toolbelt.DynamicBinderExtension;\n...\nvar obj = new MyClass();\n...\n// Call an instance method.\n// (You can pass ref \u0026 out arguments.)\nvar retval = (int)obj.ToDynamic().MethodName(arg1, ref arg2, out int arg3);\n\n// Get or set an instance property.\nvar value = (int)obj.ToDynamic().PropName;\nobj.ToDynamic().PropName = newValue;\n\n// Get or set an instance field.\nvar value = (int)obj.ToDynamic().FieldName;\nobj.ToDynamic().FieldName = newValue;\n```\n\n### Access to static members\n\nAfter importing (opening) namespace `Toolbelt`, you can use `DynamicBinder.Create\u003cT\u003e()` and `DynamicBinder.Create(Type t)` static method that returned C #4.0 `dynamic` type.\n\n```csharp\nusing Toolbelt;\n...\nvar binder = DynamicBinder.Create(typeof(Foo));\n\n// Call a static method.\n// (You can pass ref \u0026 out arguments.)\nvar retval = (int)binder.MethodName(arg1, ref arg2, out int arg3);\n\n// Get or set a static property.\nvar value = (int)binder.PropName;\nbinder.PropName = newValue;\n\n// Get or set a static field.\nvar value = (int)binder.FieldName;\nbinder.FieldName = newValue;\n```\n\n### NOTICE: Retrieving a type information of the returned value from the method calling\n\nRetrieving a type information of the return value from the method calling\n\nThe following test code will fail.\n\n```csharp\nobject bar = foo.ToDynamic().GetBarObject();\n\n// 👇 It will report \"actual is `DynamicBinder`\" !\nAssert.AreEqual(\"BarClass\", bar.GetType().Name); \n```\n\nYou should rewrite the above test code as follows.\n\n```csharp\n// Extract a `DynamicBinder` object from the C# dynamic object by casting with `as`.\nvar retval = foo.ToDynamic().GetBarObject() as DynamicBinder;\n\n// The `DynamicBinder` class exposes the `Object` property to access the bound target object.\nAssert.AreEqual(\"BarClass\", retval.Object.GetType().Name); // Green. Pass!\n```\n\nOf course, if you have the right type information, those test codes can be rewritten as the following:\n\n```csharp\nvar bar = (BarClass)foo.ToDynamic().GetBarObject();\nAssert.AreEqual(\"BarClass\", bar.GetType().Name); // Green. Pass!\n```\n\n\n## Usage - Late bind syntax\n\n### Create instance\n\nAfter importing (opening) namespace `Toolbelt`, you can use `LateBinder.CreateInstance\u003cT\u003e(...)` and `LateBinder.CreateInstance(Type t, ...)` static method to instantiate any objects with any constructors, regardless of constructor's access level (public, internal, protected, private).\n\nThose methods return an instantiated object wrapped with the `LateBinder` type.\n\n```csharp\nusing Toolbelt;\n...\n// 👇 The type of the \"dynamicObj\" is the \"LateBinder\" type.\n//    In this case, the \"dynamicObj\" is instantiated by the constructor, which has two arguments.\n//    It can be instantiated even if the constructor is private.\nvar dynamicObj = LateBinder.CreateInstance\u003cMyClass\u003e(arg1, arg2);\n\n// And it can be invoked its instance methods, regardless of its access level.\nvar retval = (int)dynamicObj.Call(\"PrivateMethodName\", arg3, arg4);\n...\n```\n\n### Access to instance members\n\nAfter importing (opening) namespace `Toolbelt.DynamicBinderExtension`, you can use `ToLateBind()` extension method that returned `LateBinder` object at any object.\n\n`LateBinder` has follow members.\n\n- `Call(name, params[] args)` method\n- `Prop[name]` property\n- `Field[name]` property\n\n```csharp\nusing Toolbelt.DynamicBinderExtension;\n...\n// Call an instance method.\nvar retval = (int)obj.ToLateBind().Call(\"MethodName\", arg1, arg2);\n\n// Get or set an instance property.\nvar value = (int)obj.ToLateBind().Prop[\"PropName\"];\nobj.ToLateBind().Prop[\"PropName\"] = newValue;\n\n// Get or set an instance field.\nvar value = (int)obj.ToLateBind().Field[\"FieldName\"];\nobj.ToLateBind().Field[\"FieldName\"] = newValue;\n```\n\n### Access to static members\n\nAfter importing (opening) namespace `Toolbelt`, you can use `LateBinder.Create\u003cT\u003e()` and `LateBinder.Create(Type t)` static method that returned `LateBinder` object.\n\n```csharp\nusing Toolbelt;\n...\nvar binder = LateBinder.Create\u003cFoo\u003e();\n// Call a static method.\nvar retval = (int)binder.Call(\"MethodName\", arg1, arg2);\n\n// Get or set a static property.\nvar value = (int)binder.Prop[\"PropName\"];\nbinder.Prop[\"PropName\"] = newValue;\n\n// Get or set a static field.\nvar value = (int)binder.Field[\"FieldName\"];\nbinder.Field[\"FieldName\"] = newValue;\n```\n\n### Call methods with `ref` \u0026 `out` arguments\n\nTo call methods with `ref` \u0026 `out` arguments, you can't pass those arguments to the `Call` method of the late-binder directly, which is different from using the \"dynamic\" syntax. Instead, follow the instructions below.\n\n```csharp\n// For example, if the definition of the \"MethodName\" static method is:\n\n// static void MethodName(int x, ref int y, out int z){\n//    z = x * y;\n//    y = y + 1;\n// }\n\n// 1. Pack all of the arguments into an object array.\nvar args = new object[] { 3, 4, default(int) };\n\n// 2. Pass it to the 2nd argument of the \"Call\" method.\nbinder.Call(\"MethodName\", args);\n\n// 3. Then, the \"args\" array will be updated.\n// args[1] -\u003e 5\n// args[2] -\u003e 12\n```\n\n## Note\n\n### No using extension methods scenario\n\nIf you feel these extension methods are dirty, you can choose no using these extension methods.\n\nInstead, you can use `LateBinder` and `DynamicBinder` class like the following code.\n\n```csharp\n// Do not open namespace \"Toolbelt.DynamicBinderExtension\".\nusing Toolbelt;\n...\n// Instead, instantiate DynamicBinder or LateBinder objects with the \"new\" keyword.\ndynamic dynamicBinder = new DynamicBinder(obj);\nvar retval = (int)dynamicBinder.MethodName(arg1, arg2);\n\nvar lateBinder = new LateBinder(obj);\nvar retval = (int)lateBinder.Call(\"MethodName\", arg1, arg2);\n```\n\n### \"Reinventing the wheel\"\n\nThere are no less than 50 packages about reflection \u0026 private members accessing.\n\n- 🔍 https://www.nuget.org/packages?q=Tags%3A%22reflection%22\n\nBut I couldn't find any packages with my favorite syntax and features :).\n\nSo I decided to \"reinvent the wheel\" by my hand.\n\n\n### Performance issue\n\nIn 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.\n\nTherefore, I think there is plenty of room for improvement to faster, more high performance.\n\nIf you prefer, you can fork this repository and improve it.\n\n## Release Notes\n\nRelease notes are [here.](https://github.com/jsakamoto/dynamicbinder/blob/master/RELEASE-NOTES.txt)\n\n## Licence\n\n- [GNU Lesser General Public License v3.0 or later](https://github.com/jsakamoto/dynamicbinder/blob/master/LICENSE)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjsakamoto%2Fdynamicbinder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjsakamoto%2Fdynamicbinder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjsakamoto%2Fdynamicbinder/lists"}