Meest efficiënte manier om de standaardconstructor van een type te krijgen

Wat is de meest efficiënte manier om de standaardconstructor (d.w.z. instantieconstructor zonder parameters) van een System.Type te krijgen?

Ik dacht aan iets in de trant van de onderstaande code, maar het lijkt erop dat er een eenvoudigere, efficiëntere manier zou moeten zijn om het te doen.

Type type = typeof(FooBar)
BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
type.GetConstructors(flags)
    .Where(constructor => constructor.GetParameters().Length == 0)
    .First();

Antwoord 1, autoriteit 100%

type.GetConstructor(Type.EmptyTypes)

Antwoord 2, autoriteit 22%

Als je het ConstructorInfo-object daadwerkelijk nodignodig hebt, ga dan naar Het antwoord van Curt Hagenlocher.

Aan de andere kant, als je echt gewoon probeert om tijdens runtime een object te maken van een System.Type, ga dan naar System.Activator.CreateInstance— het is niet alleen toekomstbestendig (Activator verwerkt meer details dan ConstructorInfo.Invoke), is het ook veelminder lelijk.


Antwoord 3, autoriteit 3%

Als je de generieke type parameter hebt, dan is het antwoord van Jeff Bridgman het beste.
Als je alleen een Type-object hebt dat het type vertegenwoordigt dat je wilt construeren, kun je Activator.CreateInstance(Type)gebruiken zoals Alex Lyman suggereerde, maar er is mij verteld dat het traag is (ik heb niet geprofileerd maar persoonlijk).

Als je merkt dat je deze objecten echter heel vaak maakt, is er een meer welsprekende benadering met dynamisch gecompileerde Linq-expressies:

using System;
using System.Linq.Expressions;
public static class TypeHelper
{
    public static Func<object> CreateDefaultConstructor(Type type)
    {
        NewExpression newExp = Expression.New(type);
        // Create a new lambda expression with the NewExpression as the body.
        var lambda = Expression.Lambda<Func<object>>(newExp);
        // Compile our new lambda expression.
        return lambda.Compile();
    }
}

Bel gewoon de afgevaardigde die naar u is teruggekeerd. U moet deze gemachtigde in de cache plaatsen, omdat het voortdurend opnieuw compileren van Linq-expressies duur kan zijn, maar als u de gemachtigde in de cache plaatst en elke keer opnieuw gebruikt, kan het erg snel gaan! Ik gebruik persoonlijk een statisch opzoekwoordenboek, geïndexeerd op type. Deze functie is handig als je te maken hebt met geserialiseerde objecten waarvan je misschien alleen de Type-informatie kent.

OPMERKING: dit kan mislukken als het type niet construeerbaar is of geen standaardconstructor heeft!


Antwoord 4

Als u alleen de standaardconstructor wilt gebruiken om de klasse te instantiëren en het type als een algemene typeparameter voor een functie wilt krijgen, kunt u het volgende doen:

T NewItUp<T>() where T : new()
{
   return new T();
}

Antwoord 5

u zou FormatterServices.GetUninitializedObject(Type) willen proberen
deze is beter dan Activator.CreateInstance

Deze methode roept de objectconstructor echter niet aan, dus als u daar initiële waarden instelt, werkt dit niet
Controleer MSDN op dit ding
http://msdn.microsoft.com/ en-us/library/system.runtime.serialization.formatterservices.getuninitializedobject.aspx

er is hier een andere manier
http://www.ozcandegirmenci. com/post/2008/02/Create-object-instances-Faster-than-Reflection.aspx

deze faalt echter als het object parametrische constructors heeft

Hopelijk helpt dit

Other episodes