Tanoda
pb_Reflection.cs
Go to the documentation of this file.
1// #define REFLECTION_DEBUG
2
3using System;
4using System.Linq;
5using System.Reflection;
6using System.Collections.Generic;
7using Newtonsoft.Json;
8using Newtonsoft.Json.Linq;
9using UnityEngine;
11
12namespace GILES
13{
18 public static class pb_Reflection
19 {
23 public static IEnumerable<PropertyInfo> GetSerializableProperties(Type type, BindingFlags flags)
24 {
25 // check that:
26 // - setter exists
27 // - flags don't care about public, or they do but setter is public anyways
28 // - it's not special
29 // - it's not tagged as obsolete or ignore
30 return type.GetProperties(flags).Where(
31 x => x.CanWrite &&
32 ( (flags & BindingFlags.Public) == 0 || x.GetSetMethod() != null ) &&
33 !x.IsSpecialName &&
34 !HasIgnoredAttribute(x) );
35 }
36
40 public static IEnumerable<FieldInfo> GetSerializableFields(Type type, BindingFlags flags)
41 {
42 return type.GetFields(flags).Where(x =>
43 ( (flags & BindingFlags.Public) == 0 || !x.IsPrivate ) &&
44 !HasIgnoredAttribute(x) );
45 }
46
51 public static Dictionary<string, object> ReflectProperties<T>(T obj)
52 {
53 return ReflectProperties<T>(obj, BindingFlags.Instance | BindingFlags.Public, null);
54 }
55
56 public static Dictionary<string, object> ReflectProperties<T>(T obj, HashSet<string> ignoreFields)
57 {
58 return ReflectProperties<T>(obj, BindingFlags.Instance | BindingFlags.Public, ignoreFields);
59 }
60
61 public static Dictionary<string, object> ReflectProperties<T>(T obj, BindingFlags flags, HashSet<string> ignoreFields)
62 {
63#if REFLECTION_DEBUG
64 System.Text.StringBuilder sb = new System.Text.StringBuilder();
65 sb.AppendLine("Component type(" + obj.GetType().ToString() + ")");
66#endif
67
68 Dictionary<string, object> properties = new Dictionary<string, object>();
69
70 Type type = obj.GetType();
71
72 foreach(PropertyInfo prop in pb_Reflection.GetSerializableProperties(type, flags))
73 {
74 try
75 {
76 bool willWrite = prop.CanWrite &&
77 !prop.IsSpecialName &&
78 !HasIgnoredAttribute(prop) &&
79 !(ignoreFields != null && ignoreFields.Contains(prop.Name));
80
81#if REFLECTION_DEBUG
82 sb.AppendLine((willWrite ? "p - " : "px- ") + prop.Name + " : " + prop.GetValue(obj, null));
83#endif
84
85 if(willWrite)
86 {
87 ParameterInfo[] parms = prop.GetIndexParameters();
88
89 if(parms != null && parms.Length > 0)
90 {
91 // Debug.LogWarning("ParameterInfo[] > 0 : " + prop.Name);
92 }
93 else
94 {
95 properties.Add(prop.Name, prop.GetValue(obj, parms));
96 }
97 }
98 }
99 catch {}
100 }
101
102 foreach(FieldInfo field in type.GetFields(flags) )
103 {
104 try
105 {
106#if REFLECTION_DEBUG
107 sb.AppendLine((HasIgnoredAttribute(field) ? "fx - " : "f - ") + field.Name + " : " + field.GetValue(obj));
108#endif
109
110 if( HasIgnoredAttribute(field) ||
111 (ignoreFields != null && ignoreFields.Contains(field.Name)))
112 continue;
113
114 properties.Add(field.Name, field.GetValue(obj));
115 }
116 catch {
117 Debug.LogError("Failed extracting property: " + field.Name);
118 }
119 }
120
121#if REFLECTION_DEBUG
122 Debug.Log(sb.ToString());
123#endif
124
125 return properties;
126 }
127
131 public static T GetValue<T>(object obj, string name)
132 {
133 return GetValue<T>(obj, name, BindingFlags.Instance | BindingFlags.Public);
134 }
135
139 public static T GetValue<T>(object obj, string name, BindingFlags flags)
140 {
141 if(obj == null)
142 return default(T);
143
144 PropertyInfo prop = obj.GetType().GetProperty(name, flags);
145
146 if(prop != null)
147 return (T) prop.GetValue(obj, null);
148
149 FieldInfo field = obj.GetType().GetField(name, flags);
150
151 if(field != null)
152 return (T) field.GetValue(obj);
153
154 return default(T);
155 }
156
157 public static bool SetValue(object obj, string name, object value)
158 {
159 return SetValue(obj, name, value, BindingFlags.Instance | BindingFlags.Public);
160 }
161
162 public static bool SetValue(object obj, string name, object value, BindingFlags flags)
163 {
164 if(obj == null)
165 return false;
166
167 PropertyInfo prop = obj.GetType().GetProperty(name, flags);
168
169 if(prop != null)
170 return SetPropertyValue(obj, prop, value);
171
172 FieldInfo field = obj.GetType().GetField(name, flags);
173
174 if(field != null)
175 return SetFieldValue(obj, field, value);
176
177 return false;
178 }
179
185 public static bool SetPropertyValue(object target, PropertyInfo propertyInfo, object value)
186 {
187 if(propertyInfo == null || target == null)
188 return false;
189
190 try
191 {
192 var val = value is JToken ? ((JToken)value).ToObject(propertyInfo.PropertyType, pb_Serialization.Serializer) : value;
193
194 if(propertyInfo.PropertyType.IsEnum)
195 {
196 int conv = (int) Convert.ChangeType(val, typeof(int));
197 propertyInfo.SetValue(target, conv, null);
198 }
199 else
200 if(val is pb_ObjectWrapper)
201 {
202 var actual = ((pb_ObjectWrapper)val).GetValue();
203 var conv = Convert.ChangeType(actual, propertyInfo.PropertyType);
204 propertyInfo.SetValue(target, conv, null);
205 }
206 else
207 {
208 var conv = Convert.ChangeType(val, propertyInfo.PropertyType);
209 propertyInfo.SetValue(target, conv, null);
210 }
211
212 return true;
213 }
214#if PB_DEBUG
215 catch(System.Exception e)
216 {
217 Debug.LogWarning(e.ToString());
218 return false;
219 }
220#else
221 catch
222 {
223 return false;
224 }
225#endif
226 }
227
232 public static bool SetFieldValue(object target, FieldInfo field, object value)
233 {
234 if(target == null || field == null)
235 return false;
236
237 try
238 {
239 var val = value is JToken ? ((JToken)value).ToObject(field.FieldType, pb_Serialization.Serializer) : value;
240
241 if(field.FieldType.IsEnum)
242 {
243 int conv = (int) Convert.ChangeType(val, typeof(int));
244 field.SetValue(target, conv);
245 }
246 else
247 if(val is pb_ObjectWrapper)
248 {
249 var actual = ((pb_ObjectWrapper)val).GetValue();
250 var conv = Convert.ChangeType(actual, field.FieldType);
251 field.SetValue(target, conv);
252 }
253 else
254 {
255 var conv = Convert.ChangeType(val, field.FieldType);
256 field.SetValue(target, conv);
257 }
258
259 return true;
260 }
261 catch(System.Exception e)
262 {
263 Debug.LogError(e.ToString());
264 return false;
265 }
266 }
267
271 public static void ApplyProperties<T>(T obj, Dictionary<string, object> properties)
272 {
273 foreach(KeyValuePair<string, object> kvp in properties)
274 {
275 SetValue(obj, kvp.Key, kvp.Value);
276 }
277 }
278
279 public static readonly HashSet<System.Type> IgnoreAttributes = new HashSet<System.Type>
280 {
281 typeof(System.ObsoleteAttribute),
283 };
284
288 public static bool HasIgnoredAttribute(Type type)
289 {
290 return type.GetCustomAttributes(true).Any(x => IgnoreAttributes.Contains(x.GetType()));
291 }
292
293 public static bool HasIgnoredAttribute<T>(T info) where T : MemberInfo
294 {
295 return info.GetCustomAttributes(true).Any(x => IgnoreAttributes.Contains(x.GetType()));
296 }
297
298 public static IEnumerable<Attribute> GetAttributes<T>(T obj)
299 {
300 return (IEnumerable<Attribute>) typeof(T).GetCustomAttributes(true);
301 }
302 }
303}
UnityEngine.Debug Debug
Definition: TanodaServer.cs:19