Refleksja – manipulacja obiektami
Refleksja, manipulacja obiektami
W poprzedniej części odczytywaliśmy metadane przy pomocy refleksji. Dzisiaj wykorzystamy te dane, ażeby manipulować obiektami, tworzyć instancje oraz zmieniać ich właściwości, czy też wywoływać ich metody. To właśnie dzięki tym mechanizmom możliwa jest implementacja kontenerów dependency injection (wykorzystanie możliwości kreacji obiektów), czy też runnery testów (odczyt atrybutów metod oraz ich wywołanie).
Nowa instancja klasy
Do stworzenia obiektu klasy należy wykorzystać klasę Activator. Ma ona kilka przeładowanych metod umożliwiających tworzenie obiektów.
Z wykorzystaniem domyślnego konstruktora
1 2 |
Type classType = typeof(ReflectionClass); object reflectionClass = Activator.CreateInstance(classType); |
lub przy wykorzystaniu konstruktora z parametrami
1 2 3 |
Type classType = typeof(ReflectionClass); object[] arguments = new object[] { "Parameter class" }; object reflectionClass = Activator.CreateInstance(classType, arguments); |
Więcej informacji https://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx
Odczyt oraz zapis właściwości
W celu pracy z właściwościami musimy pobrać jej metadane, co najprościej zrobić na podstawie jej nazwy.
1 |
PropertyInfo property = classType.GetProperty("PropertyName"); |
Tak pobrane informacje możemy wykorzystać do pobrania lub zapisania wartości. Do tego celu służą nam 2 metody GetValue oraz SetValue.
Metoda GetValue przyjmuje jako parametr obiekt, z którego wartość ma zostać odczytana, a zwraca nam obiekt, który został odczytany.
Metoda SetValue przyjmuje 2 parametry, pierwszy z nich jak w przypadku GetValue jest obiektem, który chcemy zmodyfikować, a drugi jest naszą nową wartością. Należy zwrócić uwagę na fakt, iż przy pomocy refleksji możemy zmienić również wartości z prywatnym setterem.
1 2 3 4 5 6 7 8 |
public class ReflectionClass { public string ConstructorFilledProperty { get; private set; } } PropertyInfo property = classType.GetProperty("ConstructorFilledProperty"); property.SetValue(reflectionClass, "new Value"); string propertyValue = (string)property.GetValue(reflectionClass); |
Więcej informacji https://msdn.microsoft.com/pl-pl/library/system.reflection.propertyinfo(v=vs.110).aspx
Wywoływanie metod
Ostatnim z elementów jakie chciałbym przedstawić jest wywoływanie metod. Analogicznie do właściwości najpierw musimy określić, która metoda nas interesuje.
1 |
MethodInfo someMethod = classType.GetMethod("SomeMethod"); |
Następnie musimy wywołać już metodę przy pomocy Invoke, która za parametry przyjmuje obiekt oraz tablicę obiektów parametrów.
1 |
string string returnedValue = (string)someMethod.Invoke(someClass, new object[0]); |
Więcej informacji https://msdn.microsoft.com/pl-pl/library/system.reflection.methodinfo(v=vs.110).aspx
Odczytywanie atrybutów
Ostatnią rzeczą jaką chciałbym poruszyć jest odczytywania atrybutów. Jak dobrze wiemy atrybuty można przypisywać do wielu elementów klasy. Ich odczytanie sprowadza się do wykorzystania metod GetCustomAttributes lub GetCustomAttribute na odpowiedniej klasie z informacjami (System.Type, MethodInfo, PropertyInfo etc.)
Metoda GetCustomAttributes zwraca nam wszystkie powiązane atrybuty, z kolei GetCustomAttribute przyjmuje jako parametr typ interesującego nas atrybutu.
1 2 3 4 |
MethodInfo someMethod = classType.GetMethod("SomeMethod"); IEnumerable<Attribute> attributes = someMethod.GetCustomAttributes(); PropertyInfo property = classType.GetProperty("ConstructorFilledProperty"); IEnumerable<Attribute> propertyAttributes = property.GetCustomAttributes(); |
Projekt z przykładami z tego wpisu możesz znaleźć na moim GitHubie https://github.com/Matejkos/BlogProjects/tree/master/ObjectManipulationWithReflection