CreateInstanceAccessor Class
Provides an efficient way for creating objects via dynamically created delegates.
Namespace: KGySoft.ReflectionAssembly: KGySoft.CoreLibraries (in KGySoft.CoreLibraries.dll) Version: 9.0.0-preview.1
public abstract class CreateInstanceAccessor : MemberAccessor
Public MustInherit Class CreateInstanceAccessor
Inherits MemberAccessor
public ref class CreateInstanceAccessor abstract : public MemberAccessor
[<AbstractClassAttribute>]
type CreateInstanceAccessor =
class
inherit MemberAccessor
end
- Inheritance
- Object MemberAccessor CreateInstanceAccessor
You can obtain a CreateInstanceAccessor instance by the static GetAccessor methods.
There are two overloads of them: GetAccessor(Type) can be used for types with parameterless constructors and for creating value types without a constructor,
and the GetAccessor(ConstructorInfo) overload is for creating an instance by a specified constructor (with or without parameters).
The CreateInstance(Object) method can be used to create an instance of an object in general cases.
It can be used even for constructors with parameters passed by reference. To obtain the result of possible ref/
parameters, pass a preallocated array to the CreateInstance(Object) method.
The parameters passed by reference will be assigned back to the corresponding array elements.
The other non-generic CreateInstance overloads can be used
for constructors with no more than four parameters. They provide a better performance than the general CreateInstance(Object) method
but the result of parameters passed reference will not be assigned back.
If you know the type of the created instance and the parameter types at compile time, then you can use the
generic CreateInstance methods for even better performance.
These strongly typed methods can be used as long as the constructors to invoke have no more than four parameters. Parameters passed by reference
are also supported but only as input parameters as they are not assigned back to the caller.
The first call of these methods is slower because the delegate is generated on the first access, but further calls are much faster.
The already obtained accessors are cached so subsequent GetAccessor calls return the already created accessors unless
they were dropped out from the cache, which can store about 8000 elements.
If you want to create an instance just by enlisting the constructor parameters of a
Type rather than specifying a
ConstructorInfo, then you can use the
CreateInstance
methods in the
Reflector class, which have some overloads for that purpose.
The following example compares the
CreateInstanceAccessor class with System.Reflection alternatives on .NET 8 and .NET Framework 4.8 platforms.
using System;
using System.Reflection;
using System.Runtime.Versioning;
using KGySoft.Diagnostics;
using KGySoft.Reflection;
class Example
{
private class TestClass
{
public TestClass() { }
public TestClass(int i) { }
}
private static string PlatformName => ((TargetFrameworkAttribute)Attribute.GetCustomAttribute(Assembly.GetExecutingAssembly(),
typeof(TargetFrameworkAttribute))).FrameworkDisplayName;
static void Main()
{
Type testType = typeof(TestClass);
ConstructorInfo ctor = testType.GetConstructor(Type.EmptyTypes);
CreateInstanceAccessor accessor = CreateInstanceAccessor.GetAccessor(testType);
new PerformanceTest<TestClass> { TestName = $"Default Constructor - {PlatformName}", Iterations = 1_000_000 }
.AddCase(() => new TestClass(), "Direct call")
.AddCase(() => (TestClass)Activator.CreateInstance(testType), "System.Activator.CreateInstance")
.AddCase(() => (TestClass)ctor.Invoke(null), "System.Reflection.ConstructorInfo.Invoke")
.AddCase(() => (TestClass)accessor.CreateInstance(), "CreateInstanceAccessor.CreateInstance")
.AddCase(() => accessor.CreateInstance<TestClass>(), "CreateInstanceAccessor.CreateInstance<>")
.DoTest()
.DumpResults(Console.Out);
ctor = testType.GetConstructor(new[] { typeof(int) });
accessor = CreateInstanceAccessor.GetAccessor(ctor);
#if NET8_0_OR_GREATER
ConstructorInvoker invoker = ConstructorInvoker.Create(ctor);
#endif
new PerformanceTest<TestClass> { TestName = $"Parameterized Constructor - {PlatformName}", Iterations = 1_000_000 }
.AddCase(() => new TestClass(1), "Direct call")
.AddCase(() => (TestClass)Activator.CreateInstance(testType, 1), "System.Activator.CreateInstance")
.AddCase(() => (TestClass)ctor.Invoke(new object[] { 1 }), "System.Reflection.ConstructorInfo.Invoke")
#if NET8_0_OR_GREATER
.AddCase(() => (TestClass)invoker.Invoke(1), "System.Reflection.ConstructorInvoker.Invoke (.NET 8 or later)")
#endif
.AddCase(() => (TestClass)accessor.CreateInstance(1), "CreateInstanceAccessor.CreateInstance")
.AddCase(() => accessor.CreateInstance<TestClass, int>(1), "CreateInstanceAccessor.CreateInstance<,>")
.DoTest()
.DumpResults(Console.Out);
}
}
// This code example produces a similar output to these ones:
// ==[Default Constructor - .NET 8.0 Results]================================================
// Iterations: 1,000,000
// Warming up: Yes
// Test cases: 5
// Calling GC.Collect: Yes
// Forced CPU Affinity: No
// Cases are sorted by time (quickest first)
// --------------------------------------------------
// 1. Direct call: average time: 8.66 ms
// 2. CreateInstanceAccessor.CreateInstance<>: average time: 9.48 ms (+0.83 ms / 109.53%)
// 3. CreateInstanceAccessor.CreateInstance: average time: 9.90 ms (+1.25 ms / 114.41%)
// 4. System.Activator.CreateInstance: average time: 12.84 ms (+4.18 ms / 148.32%)
// 5. System.Reflection.ConstructorInfo.Invoke: average time: 13.30 ms (+4.65 ms / 153.70%)
//
// ==[Parameterized Constructor - .NET 8.0 Results]================================================
// Iterations: 1,000,000
// Warming up: Yes
// Test cases: 6
// Calling GC.Collect: Yes
// Forced CPU Affinity: No
// Cases are sorted by time (quickest first)
// --------------------------------------------------
// 1. Direct call: average time: 5.83 ms
// 2. CreateInstanceAccessor.CreateInstance<,>: average time: 9.58 ms (+3.74 ms / 164.15%)
// 3. CreateInstanceAccessor.CreateInstance: average time: 15.45 ms (+9.61 ms / 264.79%)
// 4. System.Reflection.ConstructorInvoker.Invoke (.NET 8 or later): average time: 16.64 ms (+10.81 ms / 285.30%)
// 5. System.Reflection.ConstructorInfo.Invoke: average time: 40.69 ms (+34.85 ms / 697.44%)
// 6. System.Activator.CreateInstance: average time: 271.66 ms (+265.83 ms / 4,656.86%)
// ==[Default Constructor - .NET Framework 4.8 Results]================================================
// Iterations: 1,000,000
// Warming up: Yes
// Test cases: 5
// Calling GC.Collect: Yes
// Forced CPU Affinity: No
// Cases are sorted by time (quickest first)
// --------------------------------------------------
// 1. Direct call: average time: 5.57 ms
// 2. CreateInstanceAccessor.CreateInstance<>: average time: 14.13 ms (+8.56 ms / 253.57%)
// 3. CreateInstanceAccessor.CreateInstance: average time: 32.48 ms (+26.91 ms / 582.84%)
// 4. System.Activator.CreateInstance: average time: 48.24 ms (+42.67 ms / 865.77%)
// 5. System.Reflection.ConstructorInfo.Invoke: average time: 204.87 ms (+199.30 ms / 3,676.54%)
//
// ==[Parameterized Constructor - .NET Framework 4.8 Results]================================================
// Iterations: 1,000,000
// Warming up: Yes
// Test cases: 5
// Calling GC.Collect: Yes
// Forced CPU Affinity: No
// Cases are sorted by time (quickest first)
// --------------------------------------------------
// 1. Direct call: average time: 5.43 ms
// 2. CreateInstanceAccessor.CreateInstance<,>: average time: 14.28 ms (+8.85 ms / 263.06%)
// 3. CreateInstanceAccessor.CreateInstance: average time: 18.96 ms (+13.53 ms / 349.15%)
// 4. System.Reflection.ConstructorInfo.Invoke: average time: 199.26 ms (+193.83 ms / 3,669.64%)
// 5. System.Activator.CreateInstance: average time: 682.53 ms (+677.10 ms / 12,569.87%)
CreateInstance |
Creates a new instance using the associated Type or parameterless constructor.
See the Remarks section of the CreateInstance(Object) overload for details.
|
CreateInstance(Object) |
Creates a new instance using the associated constructor with one parameter.
See the Remarks section of the CreateInstance(Object) overload for details.
|
CreateInstance(Object) |
Creates a new instance by the associated ConstructorInfo or Type.
For types and parameterless constructors the parameters parameter is omitted.
|
CreateInstance(Object, Object) |
Creates a new instance using the associated constructor with two parameters.
See the Remarks section of the CreateInstance(Object) overload for details.
|
CreateInstance(Object, Object, Object) |
Creates a new instance using the associated constructor with three parameters.
See the Remarks section of the CreateInstance(Object) overload for details.
|
CreateInstance(Object, Object, Object, Object) |
Creates a new instance using the associated constructor with four parameters.
See the Remarks section of the CreateInstance(Object) overload for details.
|
CreateInstanceTInstance |
Creates a new instance using the associated Type or parameterless constructor.
|
CreateInstanceTInstance, T(T) |
Creates a new instance using the associated constructor with one parameter.
|
CreateInstanceTInstance, T1, T2(T1, T2) |
Creates a new instance using the associated constructor with two parameters.
|
CreateInstanceTInstance, T1, T2, T3(T1, T2, T3) |
Creates a new instance using the associated constructor with three parameters.
|
CreateInstanceTInstance, T1, T2, T3, T4(T1, T2, T3, T4) |
Creates a new instance using the associated constructor with four parameters.
|
Equals |
Determines whether the specified Object is equal to the current MemberAccessor.
(Inherited from MemberAccessor) |
GetAccessor(ConstructorInfo) |
Gets a CreateInstanceAccessor for the specified ConstructorInfo.
|
GetAccessor(Type) |
Gets a CreateInstanceAccessor for the specified Type.
Given type must have a parameterless constructor or must be a ValueType.
|
GetHashCode |
Gets a hash code for the current MemberAccessor instance.
(Inherited from MemberAccessor) |
ToString |
Returns a String that represents the current MemberAccessor.
(Inherited from MemberAccessor) |