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 Sunnov.BlogAnalytics
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 }