You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

PrivateObject.cs 44 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917
  1. // Copyright (c) Microsoft Corporation. All rights reserved.
  2. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
  3. namespace Microsoft.VisualStudio.TestTools.UnitTesting
  4. {
  5. using System;
  6. //using System.Diagnostics;
  7. //using System.Diagnostics.CodeAnalysis;
  8. using System.Globalization;
  9. using System.Reflection;
  10. /// <summary>
  11. /// This class represents the live NON public INTERNAL object in the system
  12. /// </summary>
  13. internal class PrivateObject
  14. {
  15. #region Data
  16. // bind everything
  17. private const BindingFlags BindToEveryThing = BindingFlags.Default | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public;
  18. #pragma warning disable CS0414 // The field 'PrivateObject.constructorFlags' is assigned but its value is never used
  19. private static BindingFlags constructorFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance | BindingFlags.NonPublic;
  20. #pragma warning restore CS0414 // The field 'PrivateObject.constructorFlags' is assigned but its value is never used
  21. private object target; // automatically initialized to null
  22. private Type originalType; // automatically initialized to null
  23. //private Dictionary<string, LinkedList<MethodInfo>> methodCache; // automatically initialized to null
  24. #endregion
  25. #region Constructors
  26. ///// <summary>
  27. ///// Initializes a new instance of the <see cref="PrivateObject"/> class that contains
  28. ///// the already existing object of the private class
  29. ///// </summary>
  30. ///// <param name="obj"> object that serves as starting point to reach the private members</param>
  31. ///// <param name="memberToAccess">the derefrencing string using . that points to the object to be retrived as in m_X.m_Y.m_Z</param>
  32. //[SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "obj", Justification = "We don't know anything about the object other than that it's an object, so 'obj' seems reasonable")]
  33. //public PrivateObject(object obj, string memberToAccess)
  34. //{
  35. // Helper.CheckParameterNotNull(obj, "obj", string.Empty);
  36. // ValidateAccessString(memberToAccess);
  37. // PrivateObject temp = obj as PrivateObject;
  38. // if (temp == null)
  39. // {
  40. // temp = new PrivateObject(obj);
  41. // }
  42. // // Split The access string
  43. // string[] arr = memberToAccess.Split(new char[] { '.' });
  44. // for (int i = 0; i < arr.Length; i++)
  45. // {
  46. // object next = temp.InvokeHelper(arr[i], BindToEveryThing | BindingFlags.Instance | BindingFlags.GetField | BindingFlags.GetProperty, null, CultureInfo.InvariantCulture);
  47. // temp = new PrivateObject(next);
  48. // }
  49. // this.target = temp.target;
  50. // this.originalType = temp.originalType;
  51. //}
  52. ///// <summary>
  53. ///// Initializes a new instance of the <see cref="PrivateObject"/> class that wraps the
  54. ///// specified type.
  55. ///// </summary>
  56. ///// <param name="assemblyName">Name of the assembly</param>
  57. ///// <param name="typeName">fully qualified name</param>
  58. ///// <param name="args">Argmenets to pass to the constructor</param>
  59. //public PrivateObject(string assemblyName, string typeName, params object[] args)
  60. // : this(assemblyName, typeName, null, args)
  61. //{
  62. //}
  63. ///// <summary>
  64. ///// Initializes a new instance of the <see cref="PrivateObject"/> class that wraps the
  65. ///// specified type.
  66. ///// </summary>
  67. ///// <param name="assemblyName">Name of the assembly</param>
  68. ///// <param name="typeName">fully qualified name</param>
  69. ///// <param name="parameterTypes">An array of <see cref="T:System.Type"/> objects representing the number, order, and type of the parameters for the constructor to get</param>
  70. ///// <param name="args">Argmenets to pass to the constructor</param>
  71. //public PrivateObject(string assemblyName, string typeName, Type[] parameterTypes, object[] args)
  72. // : this(Type.GetType(string.Format(CultureInfo.InvariantCulture, "{0}, {1}", typeName, assemblyName), false), parameterTypes, args)
  73. //{
  74. // Helper.CheckParameterNotNull(assemblyName, "assemblyName", string.Empty);
  75. // Helper.CheckParameterNotNull(typeName, "typeName", string.Empty);
  76. //}
  77. ///// <summary>
  78. ///// Initializes a new instance of the <see cref="PrivateObject"/> class that wraps the
  79. ///// specified type.
  80. ///// </summary>
  81. ///// <param name="type">type of the object to create</param>
  82. ///// <param name="args">Argmenets to pass to the constructor</param>
  83. //public PrivateObject(Type type, params object[] args)
  84. // : this(type, null, args)
  85. //{
  86. // Helper.CheckParameterNotNull(type, "type", string.Empty);
  87. //}
  88. ///// <summary>
  89. ///// Initializes a new instance of the <see cref="PrivateObject"/> class that wraps the
  90. ///// specified type.
  91. ///// </summary>
  92. ///// <param name="type">type of the object to create</param>
  93. ///// <param name="parameterTypes">An array of <see cref="T:System.Type"/> objects representing the number, order, and type of the parameters for the constructor to get</param>
  94. ///// <param name="args">Argmenets to pass to the constructor</param>
  95. //public PrivateObject(Type type, Type[] parameterTypes, object[] args)
  96. //{
  97. // Helper.CheckParameterNotNull(type, "type", string.Empty);
  98. // object o;
  99. // if (parameterTypes != null)
  100. // {
  101. // ConstructorInfo ci = type.GetConstructor(BindToEveryThing, null, parameterTypes, null);
  102. // if (ci == null)
  103. // {
  104. // throw new ArgumentException(FrameworkMessages.PrivateAccessorConstructorNotFound);
  105. // }
  106. // try
  107. // {
  108. // o = ci.Invoke(args);
  109. // }
  110. // catch (TargetInvocationException e)
  111. // {
  112. // Debug.Assert(e.InnerException != null, "Inner exception should not be null.");
  113. // if (e.InnerException != null)
  114. // {
  115. // throw e.InnerException;
  116. // }
  117. // throw;
  118. // }
  119. // }
  120. // else
  121. // {
  122. // o = Activator.CreateInstance(type, constructorFlags, null, args, null);
  123. // }
  124. // this.ConstructFrom(o);
  125. //}
  126. /// <summary>
  127. /// Initializes a new instance of the <see cref="PrivateObject"/> class that wraps
  128. /// the given object.
  129. /// </summary>
  130. /// <param name="obj">object to wrap</param>
  131. //[SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "obj", Justification = "We don't know anything about the object other than that it's an object, so 'obj' seems reasonable")]
  132. public PrivateObject(object obj)
  133. {
  134. Helper.CheckParameterNotNull(obj, "obj", string.Empty);
  135. this.ConstructFrom(obj);
  136. }
  137. /// <summary>
  138. /// Initializes a new instance of the <see cref="PrivateObject"/> class that wraps
  139. /// the given object.
  140. /// </summary>
  141. /// <param name="obj">object to wrap</param>
  142. /// <param name="type">PrivateType object</param>
  143. //[SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "obj", Justification = "We don't know anything about the object other than that it's an an object, so 'obj' seems reasonable")]
  144. public PrivateObject(object obj, PrivateType type)
  145. {
  146. Helper.CheckParameterNotNull(type, "type", string.Empty);
  147. this.target = obj;
  148. this.originalType = type.ReferencedType;
  149. }
  150. #endregion
  151. ///// <summary>
  152. ///// Gets or sets the target
  153. ///// </summary>
  154. //public object Target
  155. //{
  156. // get
  157. // {
  158. // return this.target;
  159. // }
  160. // set
  161. // {
  162. // Helper.CheckParameterNotNull(value, "Target", string.Empty);
  163. // this.target = value;
  164. // this.originalType = value.GetType();
  165. // }
  166. //}
  167. ///// <summary>
  168. ///// Gets the type of underlying object
  169. ///// </summary>
  170. //public Type RealType
  171. //{
  172. // get
  173. // {
  174. // return this.originalType;
  175. // }
  176. //}
  177. //private Dictionary<string, LinkedList<MethodInfo>> GenericMethodCache
  178. //{
  179. // get
  180. // {
  181. // if (this.methodCache == null)
  182. // {
  183. // this.BuildGenericMethodCacheForType(this.originalType);
  184. // }
  185. // Debug.Assert(this.methodCache != null, "Invalid method cache for type.");
  186. // return this.methodCache;
  187. // }
  188. //}
  189. /// <summary>
  190. /// returns the hash code of the target object
  191. /// </summary>
  192. /// <returns>int representing hashcode of the target object</returns>
  193. public override int GetHashCode()
  194. {
  195. //Debug.Assert(this.target != null, "target should not be null.");
  196. return this.target.GetHashCode();
  197. }
  198. /// <summary>
  199. /// Equals
  200. /// </summary>
  201. /// <param name="obj">Object with whom to compare</param>
  202. /// <returns>returns true if the objects are equal.</returns>
  203. public override bool Equals(object obj)
  204. {
  205. if (this != obj)
  206. {
  207. //Debug.Assert(this.target != null, "target should not be null.");
  208. if (typeof(PrivateObject) == obj?.GetType())
  209. {
  210. return this.target.Equals(((PrivateObject)obj).target);
  211. }
  212. else
  213. {
  214. return false;
  215. }
  216. }
  217. return true;
  218. }
  219. ///// <summary>
  220. ///// Invokes the specified method
  221. ///// </summary>
  222. ///// <param name="name">Name of the method</param>
  223. ///// <param name="args">Arguments to pass to the member to invoke.</param>
  224. ///// <returns>Result of method call</returns>
  225. //public object Invoke(string name, params object[] args)
  226. //{
  227. // Helper.CheckParameterNotNull(name, "name", string.Empty);
  228. // return this.Invoke(name, null, args, CultureInfo.InvariantCulture);
  229. //}
  230. ///// <summary>
  231. ///// Invokes the specified method
  232. ///// </summary>
  233. ///// <param name="name">Name of the method</param>
  234. ///// <param name="parameterTypes">An array of <see cref="T:System.Type"/> objects representing the number, order, and type of the parameters for the method to get.</param>
  235. ///// <param name="args">Arguments to pass to the member to invoke.</param>
  236. ///// <returns>Result of method call</returns>
  237. //public object Invoke(string name, Type[] parameterTypes, object[] args)
  238. //{
  239. // return this.Invoke(name, parameterTypes, args, CultureInfo.InvariantCulture);
  240. //}
  241. ///// <summary>
  242. ///// Invokes the specified method
  243. ///// </summary>
  244. ///// <param name="name">Name of the method</param>
  245. ///// <param name="parameterTypes">An array of <see cref="T:System.Type"/> objects representing the number, order, and type of the parameters for the method to get.</param>
  246. ///// <param name="args">Arguments to pass to the member to invoke.</param>
  247. ///// <param name="typeArguments">An array of types corresponding to the types of the generic arguments.</param>
  248. ///// <returns>Result of method call</returns>
  249. //public object Invoke(string name, Type[] parameterTypes, object[] args, Type[] typeArguments)
  250. //{
  251. // return this.Invoke(name, BindToEveryThing, parameterTypes, args, CultureInfo.InvariantCulture, typeArguments);
  252. //}
  253. ///// <summary>
  254. ///// Invokes the specified method
  255. ///// </summary>
  256. ///// <param name="name">Name of the method</param>
  257. ///// <param name="args">Arguments to pass to the member to invoke.</param>
  258. ///// <param name="culture">Culture info</param>
  259. ///// <returns>Result of method call</returns>
  260. //public object Invoke(string name, object[] args, CultureInfo culture)
  261. //{
  262. // return this.Invoke(name, null, args, culture);
  263. //}
  264. ///// <summary>
  265. ///// Invokes the specified method
  266. ///// </summary>
  267. ///// <param name="name">Name of the method</param>
  268. ///// <param name="parameterTypes">An array of <see cref="T:System.Type"/> objects representing the number, order, and type of the parameters for the method to get.</param>
  269. ///// <param name="args">Arguments to pass to the member to invoke.</param>
  270. ///// <param name="culture">Culture info</param>
  271. ///// <returns>Result of method call</returns>
  272. //public object Invoke(string name, Type[] parameterTypes, object[] args, CultureInfo culture)
  273. //{
  274. // return this.Invoke(name, BindToEveryThing, parameterTypes, args, culture);
  275. //}
  276. ///// <summary>
  277. ///// Invokes the specified method
  278. ///// </summary>
  279. ///// <param name="name">Name of the method</param>
  280. ///// <param name="bindingFlags">A bitmask comprised of one or more <see cref="T:System.Reflection.BindingFlags"/> that specify how the search is conducted.</param>
  281. ///// <param name="args">Arguments to pass to the member to invoke.</param>
  282. ///// <returns>Result of method call</returns>
  283. //public object Invoke(string name, BindingFlags bindingFlags, params object[] args)
  284. //{
  285. // return this.Invoke(name, bindingFlags, null, args, CultureInfo.InvariantCulture);
  286. //}
  287. ///// <summary>
  288. ///// Invokes the specified method
  289. ///// </summary>
  290. ///// <param name="name">Name of the method</param>
  291. ///// <param name="bindingFlags">A bitmask comprised of one or more <see cref="T:System.Reflection.BindingFlags"/> that specify how the search is conducted.</param>
  292. ///// <param name="parameterTypes">An array of <see cref="T:System.Type"/> objects representing the number, order, and type of the parameters for the method to get.</param>
  293. ///// <param name="args">Arguments to pass to the member to invoke.</param>
  294. ///// <returns>Result of method call</returns>
  295. //public object Invoke(string name, BindingFlags bindingFlags, Type[] parameterTypes, object[] args)
  296. //{
  297. // return this.Invoke(name, bindingFlags, parameterTypes, args, CultureInfo.InvariantCulture);
  298. //}
  299. ///// <summary>
  300. ///// Invokes the specified method
  301. ///// </summary>
  302. ///// <param name="name">Name of the method</param>
  303. ///// <param name="bindingFlags">A bitmask comprised of one or more <see cref="T:System.Reflection.BindingFlags"/> that specify how the search is conducted.</param>
  304. ///// <param name="args">Arguments to pass to the member to invoke.</param>
  305. ///// <param name="culture">Culture info</param>
  306. ///// <returns>Result of method call</returns>
  307. //public object Invoke(string name, BindingFlags bindingFlags, object[] args, CultureInfo culture)
  308. //{
  309. // return this.Invoke(name, bindingFlags, null, args, culture);
  310. //}
  311. ///// <summary>
  312. ///// Invokes the specified method
  313. ///// </summary>
  314. ///// <param name="name">Name of the method</param>
  315. ///// <param name="bindingFlags">A bitmask comprised of one or more <see cref="T:System.Reflection.BindingFlags"/> that specify how the search is conducted.</param>
  316. ///// <param name="parameterTypes">An array of <see cref="T:System.Type"/> objects representing the number, order, and type of the parameters for the method to get.</param>
  317. ///// <param name="args">Arguments to pass to the member to invoke.</param>
  318. ///// <param name="culture">Culture info</param>
  319. ///// <returns>Result of method call</returns>
  320. //public object Invoke(string name, BindingFlags bindingFlags, Type[] parameterTypes, object[] args, CultureInfo culture)
  321. //{
  322. // return this.Invoke(name, bindingFlags, parameterTypes, args, culture, null);
  323. //}
  324. ///// <summary>
  325. ///// Invokes the specified method
  326. ///// </summary>
  327. ///// <param name="name">Name of the method</param>
  328. ///// <param name="bindingFlags">A bitmask comprised of one or more <see cref="T:System.Reflection.BindingFlags"/> that specify how the search is conducted.</param>
  329. ///// <param name="parameterTypes">An array of <see cref="T:System.Type"/> objects representing the number, order, and type of the parameters for the method to get.</param>
  330. ///// <param name="args">Arguments to pass to the member to invoke.</param>
  331. ///// <param name="culture">Culture info</param>
  332. ///// <param name="typeArguments">An array of types corresponding to the types of the generic arguments.</param>
  333. ///// <returns>Result of method call</returns>
  334. //public object Invoke(string name, BindingFlags bindingFlags, Type[] parameterTypes, object[] args, CultureInfo culture, Type[] typeArguments)
  335. //{
  336. // Helper.CheckParameterNotNull(name, "name", string.Empty);
  337. // if (parameterTypes != null)
  338. // {
  339. // bindingFlags |= BindToEveryThing | BindingFlags.Instance;
  340. // // Fix up the parameter types
  341. // MethodInfo member = this.originalType.GetMethod(name, bindingFlags, null, parameterTypes, null);
  342. // // If the method was not found and type arguments were provided for generic paramaters,
  343. // // attempt to look up a generic method.
  344. // if ((member == null) && (typeArguments != null))
  345. // {
  346. // // This method may contain generic parameters...if so, the previous call to
  347. // // GetMethod() will fail because it doesn't fully support generic parameters.
  348. // // Look in the method cache to see if there is a generic method
  349. // // on the incoming type that contains the correct signature.
  350. // member = this.GetGenericMethodFromCache(name, parameterTypes, typeArguments, bindingFlags, null);
  351. // }
  352. // if (member == null)
  353. // {
  354. // throw new ArgumentException(
  355. // string.Format(CultureInfo.CurrentCulture, FrameworkMessages.PrivateAccessorMemberNotFound, name));
  356. // }
  357. // try
  358. // {
  359. // if (member.IsGenericMethodDefinition)
  360. // {
  361. // MethodInfo constructed = member.MakeGenericMethod(typeArguments);
  362. // return constructed.Invoke(this.target, bindingFlags, null, args, culture);
  363. // }
  364. // else
  365. // {
  366. // return member.Invoke(this.target, bindingFlags, null, args, culture);
  367. // }
  368. // }
  369. // catch (TargetInvocationException e)
  370. // {
  371. // Debug.Assert(e.InnerException != null, "Inner exception should not be null.");
  372. // if (e.InnerException != null)
  373. // {
  374. // throw e.InnerException;
  375. // }
  376. // throw;
  377. // }
  378. // }
  379. // else
  380. // {
  381. // return this.InvokeHelper(name, bindingFlags | BindingFlags.InvokeMethod, args, culture);
  382. // }
  383. //}
  384. ///// <summary>
  385. ///// Gets the array element using array of subsrcipts for each dimension
  386. ///// </summary>
  387. ///// <param name="name">Name of the member</param>
  388. ///// <param name="indices">the indices of array</param>
  389. ///// <returns>An arrya of elements.</returns>
  390. //public object GetArrayElement(string name, params int[] indices)
  391. //{
  392. // Helper.CheckParameterNotNull(name, "name", string.Empty);
  393. // return this.GetArrayElement(name, BindToEveryThing, indices);
  394. //}
  395. ///// <summary>
  396. ///// Sets the array element using array of subsrcipts for each dimension
  397. ///// </summary>
  398. ///// <param name="name">Name of the member</param>
  399. ///// <param name="value">Value to set</param>
  400. ///// <param name="indices">the indices of array</param>
  401. //public void SetArrayElement(string name, object value, params int[] indices)
  402. //{
  403. // Helper.CheckParameterNotNull(name, "name", string.Empty);
  404. // this.SetArrayElement(name, BindToEveryThing, value, indices);
  405. //}
  406. ///// <summary>
  407. ///// Gets the array element using array of subsrcipts for each dimension
  408. ///// </summary>
  409. ///// <param name="name">Name of the member</param>
  410. ///// <param name="bindingFlags">A bitmask comprised of one or more <see cref="T:System.Reflection.BindingFlags"/> that specify how the search is conducted.</param>
  411. ///// <param name="indices">the indices of array</param>
  412. ///// <returns>An arrya of elements.</returns>
  413. //public object GetArrayElement(string name, BindingFlags bindingFlags, params int[] indices)
  414. //{
  415. // Helper.CheckParameterNotNull(name, "name", string.Empty);
  416. // Array arr = (Array)this.InvokeHelper(name, BindingFlags.GetField | bindingFlags, null, CultureInfo.InvariantCulture);
  417. // return arr.GetValue(indices);
  418. //}
  419. ///// <summary>
  420. ///// Sets the array element using array of subsrcipts for each dimension
  421. ///// </summary>
  422. ///// <param name="name">Name of the member</param>
  423. ///// <param name="bindingFlags">A bitmask comprised of one or more <see cref="T:System.Reflection.BindingFlags"/> that specify how the search is conducted.</param>
  424. ///// <param name="value">Value to set</param>
  425. ///// <param name="indices">the indices of array</param>
  426. //public void SetArrayElement(string name, BindingFlags bindingFlags, object value, params int[] indices)
  427. //{
  428. // Helper.CheckParameterNotNull(name, "name", string.Empty);
  429. // Array arr = (Array)this.InvokeHelper(name, BindingFlags.GetField | bindingFlags, null, CultureInfo.InvariantCulture);
  430. // arr.SetValue(value, indices);
  431. //}
  432. ///// <summary>
  433. ///// Get the field
  434. ///// </summary>
  435. ///// <param name="name">Name of the field</param>
  436. ///// <returns>The field.</returns>
  437. //public object GetField(string name)
  438. //{
  439. // Helper.CheckParameterNotNull(name, "name", string.Empty);
  440. // return this.GetField(name, BindToEveryThing);
  441. //}
  442. ///// <summary>
  443. ///// Sets the field
  444. ///// </summary>
  445. ///// <param name="name">Name of the field</param>
  446. ///// <param name="value">value to set</param>
  447. //public void SetField(string name, object value)
  448. //{
  449. // Helper.CheckParameterNotNull(name, "name", string.Empty);
  450. // this.SetField(name, BindToEveryThing, value);
  451. //}
  452. ///// <summary>
  453. ///// Gets the field
  454. ///// </summary>
  455. ///// <param name="name">Name of the field</param>
  456. ///// <param name="bindingFlags">A bitmask comprised of one or more <see cref="T:System.Reflection.BindingFlags"/> that specify how the search is conducted.</param>
  457. ///// <returns>The field.</returns>
  458. //public object GetField(string name, BindingFlags bindingFlags)
  459. //{
  460. // Helper.CheckParameterNotNull(name, "name", string.Empty);
  461. // return this.InvokeHelper(name, BindingFlags.GetField | bindingFlags, null, CultureInfo.InvariantCulture);
  462. //}
  463. ///// <summary>
  464. ///// Sets the field
  465. ///// </summary>
  466. ///// <param name="name">Name of the field</param>
  467. ///// <param name="bindingFlags">A bitmask comprised of one or more <see cref="T:System.Reflection.BindingFlags"/> that specify how the search is conducted.</param>
  468. ///// <param name="value">value to set</param>
  469. //public void SetField(string name, BindingFlags bindingFlags, object value)
  470. //{
  471. // Helper.CheckParameterNotNull(name, "name", string.Empty);
  472. // this.InvokeHelper(name, BindingFlags.SetField | bindingFlags, new object[] { value }, CultureInfo.InvariantCulture);
  473. //}
  474. /// <summary>
  475. /// Get the field or property
  476. /// </summary>
  477. /// <param name="name">Name of the field or property</param>
  478. /// <returns>The field or property.</returns>
  479. public object GetFieldOrProperty(string name)
  480. {
  481. Helper.CheckParameterNotNull(name, "name", string.Empty);
  482. return this.GetFieldOrProperty(name, BindToEveryThing);
  483. }
  484. /// <summary>
  485. /// Sets the field or property
  486. /// </summary>
  487. /// <param name="name">Name of the field or property</param>
  488. /// <param name="value">value to set</param>
  489. public void SetFieldOrProperty(string name, object value)
  490. {
  491. Helper.CheckParameterNotNull(name, "name", string.Empty);
  492. this.SetFieldOrProperty(name, BindToEveryThing, value);
  493. }
  494. /// <summary>
  495. /// Gets the field or property
  496. /// </summary>
  497. /// <param name="name">Name of the field or property</param>
  498. /// <param name="bindingFlags">A bitmask comprised of one or more <see cref="T:System.Reflection.BindingFlags"/> that specify how the search is conducted.</param>
  499. /// <returns>The field or property.</returns>
  500. public object GetFieldOrProperty(string name, BindingFlags bindingFlags)
  501. {
  502. Helper.CheckParameterNotNull(name, "name", string.Empty);
  503. return this.InvokeHelper(name, BindingFlags.GetField | BindingFlags.GetProperty | bindingFlags, null, CultureInfo.InvariantCulture);
  504. }
  505. /// <summary>
  506. /// Sets the field or property
  507. /// </summary>
  508. /// <param name="name">Name of the field or property</param>
  509. /// <param name="bindingFlags">A bitmask comprised of one or more <see cref="T:System.Reflection.BindingFlags"/> that specify how the search is conducted.</param>
  510. /// <param name="value">value to set</param>
  511. public void SetFieldOrProperty(string name, BindingFlags bindingFlags, object value)
  512. {
  513. Helper.CheckParameterNotNull(name, "name", string.Empty);
  514. this.InvokeHelper(name, BindingFlags.SetField | BindingFlags.SetProperty | bindingFlags, new object[] { value }, CultureInfo.InvariantCulture);
  515. }
  516. ///// <summary>
  517. ///// Gets the property
  518. ///// </summary>
  519. ///// <param name="name">Name of the property</param>
  520. ///// <param name="args">Arguments to pass to the member to invoke.</param>
  521. ///// <returns>The property.</returns>
  522. //public object GetProperty(string name, params object[] args)
  523. //{
  524. // return this.GetProperty(name, null, args);
  525. //}
  526. ///// <summary>
  527. ///// Gets the property
  528. ///// </summary>
  529. ///// <param name="name">Name of the property</param>
  530. ///// <param name="parameterTypes">An array of <see cref="T:System.Type"/> objects representing the number, order, and type of the parameters for the indexed property.</param>
  531. ///// <param name="args">Arguments to pass to the member to invoke.</param>
  532. ///// <returns>The property.</returns>
  533. //public object GetProperty(string name, Type[] parameterTypes, object[] args)
  534. //{
  535. // return this.GetProperty(name, BindToEveryThing, parameterTypes, args);
  536. //}
  537. ///// <summary>
  538. ///// Set the property
  539. ///// </summary>
  540. ///// <param name="name">Name of the property</param>
  541. ///// <param name="value">value to set</param>
  542. ///// <param name="args">Arguments to pass to the member to invoke.</param>
  543. //public void SetProperty(string name, object value, params object[] args)
  544. //{
  545. // this.SetProperty(name, null, value, args);
  546. //}
  547. ///// <summary>
  548. ///// Set the property
  549. ///// </summary>
  550. ///// <param name="name">Name of the property</param>
  551. ///// <param name="parameterTypes">An array of <see cref="T:System.Type"/> objects representing the number, order, and type of the parameters for the indexed property.</param>
  552. ///// <param name="value">value to set</param>
  553. ///// <param name="args">Arguments to pass to the member to invoke.</param>
  554. //public void SetProperty(string name, Type[] parameterTypes, object value, object[] args)
  555. //{
  556. // this.SetProperty(name, BindToEveryThing, value, parameterTypes, args);
  557. //}
  558. ///// <summary>
  559. ///// Gets the property
  560. ///// </summary>
  561. ///// <param name="name">Name of the property</param>
  562. ///// <param name="bindingFlags">A bitmask comprised of one or more <see cref="T:System.Reflection.BindingFlags"/> that specify how the search is conducted.</param>
  563. ///// <param name="args">Arguments to pass to the member to invoke.</param>
  564. ///// <returns>The property.</returns>
  565. //public object GetProperty(string name, BindingFlags bindingFlags, params object[] args)
  566. //{
  567. // return this.GetProperty(name, bindingFlags, null, args);
  568. //}
  569. ///// <summary>
  570. ///// Gets the property
  571. ///// </summary>
  572. ///// <param name="name">Name of the property</param>
  573. ///// <param name="bindingFlags">A bitmask comprised of one or more <see cref="T:System.Reflection.BindingFlags"/> that specify how the search is conducted.</param>
  574. ///// <param name="parameterTypes">An array of <see cref="T:System.Type"/> objects representing the number, order, and type of the parameters for the indexed property.</param>
  575. ///// <param name="args">Arguments to pass to the member to invoke.</param>
  576. ///// <returns>The property.</returns>
  577. //public object GetProperty(string name, BindingFlags bindingFlags, Type[] parameterTypes, object[] args)
  578. //{
  579. // Helper.CheckParameterNotNull(name, "name", string.Empty);
  580. // if (parameterTypes != null)
  581. // {
  582. // PropertyInfo pi = this.originalType.GetProperty(name, bindingFlags, null, null, parameterTypes, null);
  583. // if (pi == null)
  584. // {
  585. // throw new ArgumentException(
  586. // string.Format(CultureInfo.CurrentCulture, FrameworkMessages.PrivateAccessorMemberNotFound, name));
  587. // }
  588. // return pi.GetValue(this.target, args);
  589. // }
  590. // else
  591. // {
  592. // return this.InvokeHelper(name, bindingFlags | BindingFlags.GetProperty, args, null);
  593. // }
  594. //}
  595. ///// <summary>
  596. ///// Sets the property
  597. ///// </summary>
  598. ///// <param name="name">Name of the property</param>
  599. ///// <param name="bindingFlags">A bitmask comprised of one or more <see cref="T:System.Reflection.BindingFlags"/> that specify how the search is conducted.</param>
  600. ///// <param name="value">value to set</param>
  601. ///// <param name="args">Arguments to pass to the member to invoke.</param>
  602. //public void SetProperty(string name, BindingFlags bindingFlags, object value, params object[] args)
  603. //{
  604. // this.SetProperty(name, bindingFlags, value, null, args);
  605. //}
  606. ///// <summary>
  607. ///// Sets the property
  608. ///// </summary>
  609. ///// <param name="name">Name of the property</param>
  610. ///// <param name="bindingFlags">A bitmask comprised of one or more <see cref="T:System.Reflection.BindingFlags"/> that specify how the search is conducted.</param>
  611. ///// <param name="value">value to set</param>
  612. ///// <param name="parameterTypes">An array of <see cref="T:System.Type"/> objects representing the number, order, and type of the parameters for the indexed property.</param>
  613. ///// <param name="args">Arguments to pass to the member to invoke.</param>
  614. //public void SetProperty(string name, BindingFlags bindingFlags, object value, Type[] parameterTypes, object[] args)
  615. //{
  616. // Helper.CheckParameterNotNull(name, "name", string.Empty);
  617. // if (parameterTypes != null)
  618. // {
  619. // PropertyInfo pi = this.originalType.GetProperty(name, bindingFlags, null, null, parameterTypes, null);
  620. // if (pi == null)
  621. // {
  622. // throw new ArgumentException(
  623. // string.Format(CultureInfo.CurrentCulture, FrameworkMessages.PrivateAccessorMemberNotFound, name));
  624. // }
  625. // pi.SetValue(this.target, value, args);
  626. // }
  627. // else
  628. // {
  629. // object[] pass = new object[(args?.Length ?? 0) + 1];
  630. // pass[0] = value;
  631. // args?.CopyTo(pass, 1);
  632. // this.InvokeHelper(name, bindingFlags | BindingFlags.SetProperty, pass, null);
  633. // }
  634. //}
  635. #region Private Helpers
  636. ///// <summary>
  637. ///// Validate access string
  638. ///// </summary>
  639. ///// <param name="access"> access string</param>
  640. //private static void ValidateAccessString(string access)
  641. //{
  642. // Helper.CheckParameterNotNull(access, "access", string.Empty);
  643. // if (access.Length == 0)
  644. // {
  645. // throw new ArgumentException(FrameworkMessages.AccessStringInvalidSyntax);
  646. // }
  647. // string[] arr = access.Split('.');
  648. // foreach (string str in arr)
  649. // {
  650. // if ((str.Length == 0) || (str.IndexOfAny(new char[] { ' ', '\t', '\n' }) != -1))
  651. // {
  652. // throw new ArgumentException(FrameworkMessages.AccessStringInvalidSyntax);
  653. // }
  654. // }
  655. //}
  656. /// <summary>
  657. /// Invokes the memeber
  658. /// </summary>
  659. /// <param name="name">Name of the member</param>
  660. /// <param name="bindingFlags">Additional attributes</param>
  661. /// <param name="args">Arguments for the invocation</param>
  662. /// <param name="culture">Culture</param>
  663. /// <returns>Result of the invocation</returns>
  664. private object InvokeHelper(string name, BindingFlags bindingFlags, object[] args, CultureInfo culture)
  665. {
  666. Helper.CheckParameterNotNull(name, "name", string.Empty);
  667. //Debug.Assert(this.target != null, "Internal Error: Null reference is returned for internal object");
  668. // Invoke the actual Method
  669. try
  670. {
  671. return this.originalType.InvokeMember(name, bindingFlags, null, this.target, args, culture);
  672. }
  673. catch (TargetInvocationException e)
  674. {
  675. //Debug.Assert(e.InnerException != null, "Inner exception should not be null.");
  676. if (e.InnerException != null)
  677. {
  678. throw e.InnerException;
  679. }
  680. throw;
  681. }
  682. }
  683. private void ConstructFrom(object obj)
  684. {
  685. Helper.CheckParameterNotNull(obj, "obj", string.Empty);
  686. this.target = obj;
  687. this.originalType = obj.GetType();
  688. }
  689. //private void BuildGenericMethodCacheForType(Type t)
  690. //{
  691. // Debug.Assert(t != null, "type should not be null.");
  692. // this.methodCache = new Dictionary<string, LinkedList<MethodInfo>>();
  693. // MethodInfo[] members = t.GetMethods(BindToEveryThing);
  694. // LinkedList<MethodInfo> listByName; // automatically initialized to null
  695. // foreach (MethodInfo member in members)
  696. // {
  697. // if (member.IsGenericMethod || member.IsGenericMethodDefinition)
  698. // {
  699. // if (!this.GenericMethodCache.TryGetValue(member.Name, out listByName))
  700. // {
  701. // listByName = new LinkedList<MethodInfo>();
  702. // this.GenericMethodCache.Add(member.Name, listByName);
  703. // }
  704. // Debug.Assert(listByName != null, "list should not be null.");
  705. // listByName.AddLast(member);
  706. // }
  707. // }
  708. //}
  709. ///// <summary>
  710. ///// Extracts the most appropriate generic method signature from the current private type.
  711. ///// </summary>
  712. ///// <param name="methodName">The name of the method in which to search the signature cache.</param>
  713. ///// <param name="parameterTypes">An array of types corresponding to the types of the parameters in which to search.</param>
  714. ///// <param name="typeArguments">An array of types corresponding to the types of the generic arguments.</param>
  715. ///// <param name="bindingFlags"><see cref="BindingFlags"/> to further filter the method signatures.</param>
  716. ///// <param name="modifiers">Modifiers for parameters.</param>
  717. ///// <returns>A methodinfo instance.</returns>
  718. //private MethodInfo GetGenericMethodFromCache(string methodName, Type[] parameterTypes, Type[] typeArguments, BindingFlags bindingFlags, ParameterModifier[] modifiers)
  719. //{
  720. // Debug.Assert(!string.IsNullOrEmpty(methodName), "Invalid method name.");
  721. // Debug.Assert(parameterTypes != null, "Invalid parameter type array.");
  722. // Debug.Assert(typeArguments != null, "Invalid type arguments array.");
  723. // // Build a preliminary list of method candidates that contain roughly the same signature.
  724. // var methodCandidates = this.GetMethodCandidates(methodName, parameterTypes, typeArguments, bindingFlags, modifiers);
  725. // // Search of ambiguous methods (methods with the same signature).
  726. // MethodInfo[] finalCandidates = new MethodInfo[methodCandidates.Count];
  727. // methodCandidates.CopyTo(finalCandidates, 0);
  728. // if ((parameterTypes != null) && (parameterTypes.Length == 0))
  729. // {
  730. // for (int i = 0; i < finalCandidates.Length; i++)
  731. // {
  732. // MethodInfo methodInfo = finalCandidates[i];
  733. // if (!RuntimeTypeHelper.CompareMethodSigAndName(methodInfo, finalCandidates[0]))
  734. // {
  735. // throw new AmbiguousMatchException();
  736. // }
  737. // }
  738. // // All the methods have the exact same name and sig so return the most derived one.
  739. // return RuntimeTypeHelper.FindMostDerivedNewSlotMeth(finalCandidates, finalCandidates.Length) as MethodInfo;
  740. // }
  741. // // Now that we have a preliminary list of candidates, select the most appropriate one.
  742. // return RuntimeTypeHelper.SelectMethod(bindingFlags, finalCandidates, parameterTypes, modifiers) as MethodInfo;
  743. //}
  744. //private LinkedList<MethodInfo> GetMethodCandidates(string methodName, Type[] parameterTypes, Type[] typeArguments, BindingFlags bindingFlags, ParameterModifier[] modifiers)
  745. //{
  746. // Debug.Assert(!string.IsNullOrEmpty(methodName), "methodName should not be null.");
  747. // Debug.Assert(parameterTypes != null, "parameterTypes should not be null.");
  748. // Debug.Assert(typeArguments != null, "typeArguments should not be null.");
  749. // LinkedList<MethodInfo> methodCandidates = new LinkedList<MethodInfo>();
  750. // LinkedList<MethodInfo> methods = null;
  751. // if (!this.GenericMethodCache.TryGetValue(methodName, out methods))
  752. // {
  753. // return methodCandidates;
  754. // }
  755. // Debug.Assert(methods != null, "methods should not be null.");
  756. // foreach (MethodInfo candidate in methods)
  757. // {
  758. // bool paramMatch = true;
  759. // ParameterInfo[] candidateParams = null;
  760. // Type[] genericArgs = candidate.GetGenericArguments();
  761. // Type sourceParameterType = null;
  762. // if (genericArgs.Length != typeArguments.Length)
  763. // {
  764. // continue;
  765. // }
  766. // // Since we can't just get the correct MethodInfo from Reflection,
  767. // // we will just match the number of parameters, their order, and their type
  768. // var methodCandidate = candidate;
  769. // candidateParams = methodCandidate.GetParameters();
  770. // if (candidateParams.Length != parameterTypes.Length)
  771. // {
  772. // continue;
  773. // }
  774. // // Exact binding
  775. // if ((bindingFlags & BindingFlags.ExactBinding) != 0)
  776. // {
  777. // int i = 0;
  778. // foreach (ParameterInfo candidateParam in candidateParams)
  779. // {
  780. // sourceParameterType = parameterTypes[i++];
  781. // if (candidateParam.ParameterType.ContainsGenericParameters)
  782. // {
  783. // // Since we have a generic parameter here, just make sure the IsArray matches.
  784. // if (candidateParam.ParameterType.IsArray != sourceParameterType.IsArray)
  785. // {
  786. // paramMatch = false;
  787. // break;
  788. // }
  789. // }
  790. // else
  791. // {
  792. // if (candidateParam.ParameterType != sourceParameterType)
  793. // {
  794. // paramMatch = false;
  795. // break;
  796. // }
  797. // }
  798. // }
  799. // if (paramMatch)
  800. // {
  801. // methodCandidates.AddLast(methodCandidate);
  802. // continue;
  803. // }
  804. // }
  805. // else
  806. // {
  807. // methodCandidates.AddLast(methodCandidate);
  808. // }
  809. // }
  810. // return methodCandidates;
  811. //}
  812. #endregion
  813. }
  814. }