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

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