PerformantReflection 1.8.1
dotnet add package PerformantReflection --version 1.8.1
NuGet\Install-Package PerformantReflection -Version 1.8.1
<PackageReference Include="PerformantReflection" Version="1.8.1" />
paket add PerformantReflection --version 1.8.1
#r "nuget: PerformantReflection, 1.8.1"
// Install PerformantReflection as a Cake Addin #addin nuget:?package=PerformantReflection&version=1.8.1 // Install PerformantReflection as a Cake Tool #tool nuget:?package=PerformantReflection&version=1.8.1
PerformantReflection
A super small library for making Reflection FAST.
The current version exposes Properties, allowing you to read their values as well as write new values with basically no performance penalty compared to when not using Reflection.
It has a sped-up version of the .Net built-in Activator.CreateInstance
: TypeInstantiator.CreateInstance
.
This is archived by reflecting types just once, and emitting IL to create new dynamic methods. Finally a delegate is
cached for these dynamic methods, and invoking these delegates
has basically no performance penalty.
It also has an ObjectBuilder
/InterfaceObjectBuilder
for instantiating classes/interfaces and setting properties with
private setters to some custom value. I personally use this
for Fakes in integration tests, when Mocks don't cut it.
Finally there's the InterfaceImplementationGenerator
which allows you to create implementation classes of interfaces
on-the-fly. This can be quite useful for exchanging e.g. JSON
based messages.
Installation
I recommend using the NuGet package: PerformantReflection however feel free to clone the source instead if that suits your needs better.
Usage
For properties
Simply instantiate an ObjectAccessor
and feed it the object you want to access.
Then you can loop over the Properties
, index into them with ["PropertyName"]
or use TryGetValue
if you're unsure
whether the property even exists:
Examples:
class User {
public string Username { get;set; }
}
var user = new User {
Username = "Old username"
};
var accessor = new ObjectAccessor(user);
var existingUsername = accessor.Properties["Username"].GetValue();
accessor.Properties["Username"].SetValue("New username");
For instantiating types
Simply call TypeInstantiator.CreateInstance(someType)
similar to how you would with Activator.CreateInstance
- it's
that simple 😃
Or if you need to populate properties with public getters but private setters, use the ObjectBuilder
like this:
var instance = new ObjectBuilder<YourType>()
.With(inst => inst.Id, Guid.NewGuid()) // The Id property will be set to Guid.NewGuid()
.With(inst => inst.Name, "Some name") // Likewise Name will be set to "Some name"
.Build();
For iterating over properties of types
Use the TypePropertyCache
to get a collection of properties for any given type. As the name implies this information
is cached for rapid repeated lookup.
Furthermore the resulting type PropertyInformation
holds high-performance getter and setter methods (assuming the
property in question has a getter or setter)
For generating implementation types based on interfaces
Simply call InterfaceImplementationGenerator.GenerateImplementationType<T>
or CreateInstance<T>
depending on your
needs.
This will generate an implementation type for the interface (and instantiate an instance if
calling CreateInstance<T>
).
This can be quite useful when sending e.g. JSON serialized messages where you don't want to share the implementation
class, but rather just the interface.
It can also be useful for situations where your class has private setters and you want to maintain that.
Simply specify an interface with only the getters, and use GenerateImplementationType<T>
to implement a class with a
public setter that allows you to deserialize the JSON, yet
doesn't allow the caller to mutate the resulting instance.
Furthermore if you want to build an instance of your interface, with predefined values (quite useful for unit testing),
use the InterfaceObjectBuilder
in the same fashion as
the "ordinary" ObjectBuilder
:
var instance = new InterfaceObjectBuilder<IYourInterface>()
.With(inst => inst.Id, Guid.NewGuid()) // The Id property will be set to Guid.NewGuid()
.With(inst => inst.Name, "Some name") // Likewise Name will be set to "Some name"
.Build();
For Json deserialization of properties with private setters
Either use the JsonSerializerOptionsFactory
class to create a new JsonSerializerOptions
instance with the necessary
configuration, or use the extension method AddPrivateDeserializationSupport
of JsonSerializerOptions
to configure
an existing options instance.
Both reside in the PerformantReflection.Json
namespace.
An example:
public class User
{
public Guid Id { get; private set; }
public User()
{
Id = Guid.NewGuid();
}
}
var user = new User();
var json = JsonSerializer.Serialize(user);
var options = JsonSerializerOptionsFactory.CreateOptionsWithPrivateDeserializationSupport();
var deserialized = JsonSerializer.Deserialize<User>(json, options);
// deserialized will have the Id deserialized as well now
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. 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. |
-
net8.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
1.8.1 | 33,105 | 5/3/2024 |
1.8.0 | 558 | 4/27/2024 |
1.7.6 | 715 | 3/26/2024 |
1.7.5 | 5,593 | 1/13/2024 |
1.7.4 | 5,598 | 11/11/2023 |
1.7.3 | 582 | 9/20/2023 |
1.7.2 | 860 | 6/29/2023 |
1.7.1 | 588 | 6/12/2023 |
1.7.0 | 162 | 6/12/2023 |
1.6.0 | 200 | 6/9/2023 |
1.5.1 | 432 | 5/31/2023 |
1.5.0 | 159 | 5/30/2023 |
1.4.0 | 193 | 5/9/2023 |
1.3.0 | 2,398 | 10/4/2022 |
1.2.1 | 407 | 7/23/2022 |
1.2.0 | 408 | 6/23/2022 |
1.1.1 | 415 | 6/20/2022 |
1.1.0 | 400 | 6/20/2022 |
1.0.0 | 1,547 | 5/9/2022 |