Nie zawsze można znać Type
obiekt w czasie kompilacji, ale może być konieczne utworzenie instancji obiektu Type
.
Jak uzyskać nową instancję obiektu z Type
?
c#
.net
performance
reflection
types
tags2k
źródło
źródło
ObjectType instance
spełnia warunek PO „Nie zawsze można poznać typ obiektu w czasie kompilacji”? : Pobject instance = Activator.CreateInstance(...);
.Activator
Klasa ma ogólny wariant, który sprawia, że nieco łatwiej:źródło
dynamic
konstrukt, który robi umożliwić takie konstrukty, ale w większości przypadków ta odpowiedź nadal obejmuje ją.Skompilowane wyrażenie jest najlepszym sposobem! (dla wydajności, aby wielokrotnie tworzyć instancję w środowisku wykonawczym).
Statystyki (2012):
Statystyki (2015, .net 4.5, x64):
Statystyki (2015, .net 4.5, x86):
Statystyki (2017, LINQPad 5.22.02 / x64 / .NET 4.6):
Statystyki (2019, x64 / .NET 4.8):
Statystyki (2019, x64 / .NET Core 3.0):
Pełny kod:
źródło
X
jest w czasie wykonywania?Type
.Jedną z realizacji tego problemu jest próba wywołania konstruktora bez parametrów typu:
Oto to samo podejście zawarte w ogólnej metodzie:
źródło
To całkiem proste. Załóżmy, że twoja nazwa klasy to
Car
i przestrzeń nazw toVehicles
, a następnie przekaż parametr,Vehicles.Car
który zwraca obiekt typuCar
. W ten sposób możesz dynamicznie tworzyć dowolne wystąpienia dowolnej klasy.Jeśli twoje w pełni kwalifikowane imię (tj.
Vehicles.Car
W tym przypadku) znajduje się w innym zbiorze,Type.GetType
będzie puste. W takich przypadkach przeglądasz wszystkie zespoły i odnajdujeszType
. W tym celu możesz użyć poniższego koduI możesz uzyskać instancję, wywołując powyższą metodę.
źródło
Jeśli dotyczy to czegoś, co będzie często nazywane w instancji aplikacji, kompilowanie i buforowanie dynamicznego kodu jest znacznie szybsze niż użycie aktywatora lub
ConstructorInfo.Invoke()
. Dwie proste opcje dynamicznej kompilacji to skompilowane wyrażenia Linq lub kilka prostychIL
kodów operacyjnych iDynamicMethod
. Tak czy inaczej, różnica jest ogromna, gdy zaczynasz wchodzić w ciasne pętle lub wiele połączeń.źródło
Czy ogólne nie
T t = new T();
zadziałałoby?źródło
Jeśli chcesz użyć domyślnego konstruktora, to rozwiązanie wykorzystujące
System.Activator
przedstawione wcześniej jest prawdopodobnie najwygodniejsze. Jeśli jednak typowi brakuje domyślnego konstruktora lub musisz użyć innego niż domyślny konstruktora, wówczas można użyć odbicia lubSystem.ComponentModel.TypeDescriptor
. W przypadku refleksji wystarczy znać tylko nazwę typu (wraz z przestrzenią nazw).Przykład użycia odbicia:
Przykład użycia
TypeDescriptor
:źródło
args[]
było dokładnie to, co znalazłem na to pytanie, dzięki!Bez użycia Refleksji:
źródło
Biorąc pod uwagę ten problem, Aktywator będzie działał, gdy pojawi się parametryczny ctor. Jeśli jest to ograniczenie, rozważ użycie
źródło
źródło
Mogę przejść przez to pytanie, ponieważ chciałem zaimplementować prostą metodę CloneObject dla dowolnej klasy (z domyślnym konstruktorem)
Metodą ogólną można wymagać, aby typ implementował metodę New ().
Zakładając, że nie jest to rodzaj, załóż, że typ ma domyślnego konstruktora, a jeśli nie, złap wyjątek.
źródło