1: /*******************************************************************************
2: * InvokeHelper.cs
3: * A thread-safe control invoker helper class.
4: * -----------------------------------------------------------------------------
5: * Project:Conmajia.Controls
6: * Author:Conmajia
7: * Url:conmajia@gmail.com
8: * History:
9: * 4th Aug., 2012
10: * Added support for "Non-control" controls (such as ToolStripItem).
11: *
12: * 4th Aug., 2012
13: * Initiated.
14: ******************************************************************************/
15: using System;
16: using System.Collections.Generic;
17: using System.Reflection;
18: using System.Text;
19: using System.Windows.Forms;
20:
21: namespace InvokerHelperDemo
22: {
23: /// <summary>
24: /// A thread-safe control invoker helper class.
25: /// </summary>
26: public class InvokeHelper
27: {
28: #region delegates
29: private delegate object MethodInvoker(Control control, string methodName, params object[] args);
30:
31: private delegate object PropertyGetInvoker(Control control, object noncontrol, string propertyName);
32: private delegate void PropertySetInvoker(Control control, object noncontrol, string propertyName, object value);
33: #endregion
34:
35: #region static methods
36: // helpers
37: private static PropertyInfo GetPropertyInfo(Control control, object noncontrol, string propertyName)
38: {
39: if (control != null && !string.IsNullOrEmpty(propertyName))
40: {
41: PropertyInfo pi = null;
42: Type t = null;
43:
44: if (noncontrol != null)
45: t = noncontrol.GetType();
46: else
47: t = control.GetType();
48:
49: pi = t.GetProperty(propertyName);
50:
51: if (pi == null)
52: throw new InvalidOperationException(
53: string.Format(
54: "Can't find property {0} in {1}.",
55: propertyName,
56: t.ToString()
57: ));
58:
59: return pi;
60: }
61: else
62: throw new ArgumentNullException("Invalid argument.");
63: }
64:
65: // outlines
66: public static object Invoke(Control control, string methodName, params object[] args)
67: {
68: if (control != null && !string.IsNullOrEmpty(methodName))
69: if (control.InvokeRequired)
70: return control.Invoke(
71: new MethodInvoker(Invoke),
72: control,
73: methodName,
74: args
75: );
76: else
77: {
78: MethodInfo mi = null;
79:
80: if (args != null && args.Length > 0)
81: {
82: Type[] types = new Type[args.Length];
83: for (int i = 0; i < args.Length; i++)
84: {
85: if (args[i] != null)
86: types[i] = args[i].GetType();
87: }
88:
89: mi = control.GetType().GetMethod(methodName, types);
90: }
91: else
92: mi = control.GetType().GetMethod(methodName);
93:
94: // check method info you get
95: if (mi != null)
96: return mi.Invoke(control, args);
97: else
98: throw new InvalidOperationException("Invalid method.");
99: }
100: else
101: throw new ArgumentNullException("Invalid argument.");
102: }
103:
104: public static object Get(Control control, string propertyName)
105: {
106: return Get(control, null, propertyName);
107: }
108: public static object Get(Control control, object noncontrol, string propertyName)
109: {
110: if (control != null && !string.IsNullOrEmpty(propertyName))
111: if (control.InvokeRequired)
112: return control.Invoke(new PropertyGetInvoker(Get),
113: control,
114: noncontrol,
115: propertyName
116: );
117: else
118: {
119: PropertyInfo pi = GetPropertyInfo(control, noncontrol, propertyName);
120: object invokee = (noncontrol == null) ? control : noncontrol;
121:
122: if (pi != null)
123: if (pi.CanRead)
124: return pi.GetValue(invokee, null);
125: else
126: throw new FieldAccessException(
127: string.Format(
128: "{0}.{1} is a write-only property.",
129: invokee.GetType().ToString(),
130: propertyName
131: ));
132:
133: return null;
134: }
135: else
136: throw new ArgumentNullException("Invalid argument.");
137: }
138:
139: public static void Set(Control control, string propertyName, object value)
140: {
141: Set(control, null, propertyName, value);
142: }
143: public static void Set(Control control, object noncontrol, string propertyName, object value)
144: {
145: if (control != null && !string.IsNullOrEmpty(propertyName))
146: if (control.InvokeRequired)
147: control.Invoke(new PropertySetInvoker(Set),
148: control,
149: noncontrol,
150: propertyName,
151: value
152: );
153: else
154: {
155: PropertyInfo pi = GetPropertyInfo(control, noncontrol, propertyName);
156: object invokee = (noncontrol == null) ? control : noncontrol;
157:
158: if (pi != null)
159: if (pi.CanWrite)
160: pi.SetValue(invokee, value, null);
161: else
162: throw new FieldAccessException(
163: string.Format(
164: "{0}.{1} is a read-only property.",
165: invokee.GetType().ToString(),
166: propertyName
167: ));
168: }
169: else
170: throw new ArgumentNullException("Invalid argument.");
171: }
172: #endregion
173: }
174: }