Szorosan követi az előző bejegyzés témáját a mostani is, újra a reflection van középpontban. Ezúttal a reflectionön keresztül megszerzett propertyk (ld. PropertyInfo) gyakori hozzáférésének optimalizálása lesz a figyelem középpontjában.
Propertyhez hozzáférni alapvetően a GetValue és a SetValue metódusokon keresztül lehet, ezeknek azonban a közös tulajdonsága, hogy lassúak. Gyakori hozzáférés esetén ez értelemszerűen problémás.
Trükközésre aránylag kevés lehetőség van, ugyanakkor egy lehetőség adott. A PropertyInfo objektumnak van kettő, GetMethod és SetMethod propertyje, egyenként egy MemberInfót, pontosabban egy MethodInfo-t adnak vissza.
Ez az osztály ugyan még mindig nagyon relfection-alapú és mint korábban mutattuk egy Invoke hívással a kívánt eredményt el is érhető. Ennél azonban – tekintve hogy optimalizálni próbálunk – a CreateDelegate metódusának meghívása. Ezzel egy kívánt típusú delegált visszakapható. Érdemes itt mondjuk nem nagyon elkalandozni, szerencsére a .NET környezetben ilyesmire általánosan használt delegáltak – a Func és az Action – tökéletesen működnek.
Egy egyszerű kódrészlet a használatukra:
public class GetSet<T, K> { public Func<T, K> Getter { get; private set; } public Action<T, K> Setter { get; private set; } public Type ValueType { get; } public List<string> Attributes { get; } = new List<string>(); public GetSet() { this.ValueType = typeof(K); } public GetSet(PropertyInfo info): this() { this.Init(info); } public bool Init(PropertyInfo info) { bool valid = false; MethodInfo setMethod = info.GetSetMethod(); MethodInfo getMethod = info.GetGetMethod(); if(setMethod != null && getMethod != null) { this.Setter = (Action<T, K>)Delegate.CreateDelegate(typeof(Action<T, K>), null, setMethod); this.Getter = (Func<T, K>)Delegate.CreateDelegate(typeof(Func<T, K>), null, getMethod); valid = true; } return valid; } }
A generikusok közül a T a propertyInfo által leírt property t tartalmazó objektum típusa, a K maga a property típusa. Használni már nagyon egyszerű, amint sikerült léterozni a GetSet objektumunkat, már csak a Getter és Setter delegáltakra kell ráhívni:
int value = getSet.Getter(obj); getSet.Setter(obj, value);
Ajánljuk ennek a megoldásnak a használatát? Egyértelműen nem. De ha nincs más választás, ezeket az apró trükköket bevetve könnyebbé tehetjük az életünket.