0
|
1 using System;
|
|
2 using System.IO;
|
|
3 using System.Linq;
|
|
4 using System.Reflection;
|
|
5 using System.Threading;
|
|
6 using System.Xml.Linq;
|
|
7
|
|
8 namespace BLToolkit.Reflection.Extension
|
|
9 {
|
|
10 public class TypeExtension
|
|
11 {
|
|
12 #region Consts
|
|
13
|
|
14 public static class NodeName
|
|
15 {
|
|
16 public const string Type = "Type";
|
|
17 public const string Member = "Member";
|
|
18 public const string Association = "Association";
|
|
19 public const string Relation = "Relation";
|
|
20 public const string MasterIndex = "MasterIndex";
|
|
21 public const string SlaveIndex = "SlaveIndex";
|
|
22 }
|
|
23
|
|
24 public static class AttrName
|
|
25 {
|
|
26 public const string Name = "Name";
|
|
27 public const string DestinationType = "DestinationType";
|
|
28 }
|
|
29
|
|
30 public static class ValueName
|
|
31 {
|
|
32 public const char Delimiter = '-';
|
|
33 public const string Value = "Value";
|
|
34 public const string Type = "Type";
|
|
35 public const string ValueType = "Value-Type";
|
|
36 public const string TypePostfix = "-Type";
|
|
37 }
|
|
38
|
|
39 #endregion
|
|
40
|
|
41 #region Public Instance Members
|
|
42
|
|
43 public TypeExtension()
|
|
44 : this(new MemberExtensionCollection(), new AttributeNameCollection())
|
|
45 {
|
|
46 }
|
|
47
|
|
48 private TypeExtension(
|
|
49 MemberExtensionCollection members,
|
|
50 AttributeNameCollection attributes)
|
|
51 {
|
|
52 _members = members;
|
|
53 _attributes = attributes;
|
|
54 }
|
|
55
|
|
56 public string Name { get; set; }
|
|
57
|
|
58 public MemberExtension this[string memberName]
|
|
59 {
|
|
60 get { return _members[memberName]; }
|
|
61 }
|
|
62
|
|
63 private readonly MemberExtensionCollection _members;
|
|
64 public MemberExtensionCollection Members
|
|
65 {
|
|
66 get { return _members; }
|
|
67 }
|
|
68
|
|
69 private readonly AttributeNameCollection _attributes;
|
|
70 public AttributeNameCollection Attributes
|
|
71 {
|
|
72 get { return _attributes; }
|
|
73 }
|
|
74
|
|
75 private static readonly TypeExtension _null = new TypeExtension(MemberExtensionCollection.Null, AttributeNameCollection.Null);
|
|
76 public static TypeExtension Null
|
|
77 {
|
|
78 get { return _null; }
|
|
79 }
|
|
80
|
|
81 #endregion
|
|
82
|
|
83 #region Conversion
|
|
84
|
|
85 public static bool ToBoolean(object value, bool defaultValue)
|
|
86 {
|
|
87 return value == null? defaultValue: ToBoolean(value);
|
|
88 }
|
|
89
|
|
90 public static bool ToBoolean(object value)
|
|
91 {
|
|
92 if (value != null)
|
|
93 {
|
|
94 if (value is bool)
|
|
95 return (bool)value;
|
|
96
|
|
97 var s = value as string;
|
|
98
|
|
99 if (s != null)
|
|
100 {
|
|
101 if (s == "1")
|
|
102 return true;
|
|
103
|
|
104 s = s.ToLower();
|
|
105
|
|
106 if (s == "true" || s == "yes" || s == "on")
|
|
107 return true;
|
|
108 }
|
|
109
|
|
110 return Convert.ToBoolean(value);
|
|
111 }
|
|
112
|
|
113 return false;
|
|
114 }
|
|
115
|
|
116 public static object ChangeType(object value, Type type)
|
|
117 {
|
|
118 if (value == null || type == value.GetType())
|
|
119 return value;
|
|
120
|
|
121 if (type == typeof(string))
|
|
122 return value.ToString();
|
|
123
|
|
124 if (type == typeof(bool))
|
|
125 return ToBoolean(value);
|
|
126
|
|
127 if (type.IsEnum)
|
|
128 {
|
|
129 if (value is string)
|
|
130 return Enum.Parse(type, value.ToString(), false);
|
|
131 }
|
|
132
|
|
133 return Convert.ChangeType(value, type, Thread.CurrentThread.CurrentCulture);
|
|
134 }
|
|
135
|
|
136 #endregion
|
|
137
|
|
138 #region Public Static Members
|
|
139
|
|
140 public static ExtensionList GetExtensions(string xmlFile)
|
|
141 {
|
|
142 return GetExtensions(xmlFile, Assembly.GetCallingAssembly());
|
|
143 }
|
|
144
|
|
145 public static ExtensionList GetExtensions(string xmlFile, Assembly assembly)
|
|
146 {
|
|
147 StreamReader streamReader = null;
|
|
148
|
|
149 try
|
|
150 {
|
|
151 if (File.Exists(xmlFile))
|
|
152 {
|
|
153 streamReader = File.OpenText(xmlFile);
|
|
154 }
|
|
155 #if !SILVERLIGHT
|
|
156 else
|
|
157 {
|
|
158 var combinePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, xmlFile);
|
|
159
|
|
160 if (File.Exists(combinePath))
|
|
161 streamReader = File.OpenText(combinePath);
|
|
162 }
|
|
163 #endif
|
|
164
|
|
165 var embedded = streamReader == null;
|
|
166 var stream = embedded ? assembly.GetManifestResourceStream(xmlFile) : streamReader.BaseStream;
|
|
167
|
|
168 if (embedded && stream == null)
|
|
169 {
|
|
170 var names = assembly.GetManifestResourceNames();
|
|
171
|
|
172 // Prepare file name with a dot to avoid partial name matching.
|
|
173 //
|
|
174 xmlFile = "." + xmlFile;
|
|
175
|
|
176 foreach (var name in names)
|
|
177 {
|
|
178 if (name.EndsWith(xmlFile))
|
|
179 {
|
|
180 stream = assembly.GetManifestResourceStream(name);
|
|
181 break;
|
|
182 }
|
|
183 }
|
|
184 }
|
|
185
|
|
186 if (stream == null)
|
|
187 throw new TypeExtensionException(
|
|
188 string.Format("Could not find file '{0}'.", xmlFile));
|
|
189
|
|
190 using (stream)
|
|
191 return GetExtensions(stream);
|
|
192 }
|
|
193 finally
|
|
194 {
|
|
195 if (streamReader != null)
|
|
196 streamReader.Close();
|
|
197 }
|
|
198 }
|
|
199
|
|
200 public static ExtensionList GetExtensions(Stream xmlDocStream)
|
|
201 {
|
|
202 var doc = XDocument.Load(new StreamReader(xmlDocStream));
|
|
203
|
|
204 return CreateTypeInfo(doc);
|
|
205 }
|
|
206
|
|
207 public static TypeExtension GetTypeExtension(Type type, ExtensionList typeExtensions)
|
|
208 {
|
|
209 var attrs = type.GetCustomAttributes(typeof(TypeExtensionAttribute), true);
|
|
210
|
|
211 if (attrs != null && attrs.Length != 0)
|
|
212 {
|
|
213 var attr = (TypeExtensionAttribute)attrs[0];
|
|
214
|
|
215 if (!string.IsNullOrEmpty(attr.FileName))
|
|
216 typeExtensions = GetExtensions(attr.FileName, type.Assembly);
|
|
217
|
|
218 if (typeExtensions != null && !string.IsNullOrEmpty(attr.TypeName))
|
|
219 return typeExtensions[attr.TypeName];
|
|
220 }
|
|
221
|
|
222 return typeExtensions != null? typeExtensions[type]: Null;
|
|
223 }
|
|
224
|
|
225 #endregion
|
|
226
|
|
227 #region Private Static Members
|
|
228
|
|
229 private static ExtensionList CreateTypeInfo(XDocument doc)
|
|
230 {
|
|
231 var list = new ExtensionList();
|
|
232
|
|
233 foreach (var typeNode in doc.Root.Elements().Where(_ => _.Name.LocalName == NodeName.Type))
|
|
234 list.Add(ParseType(typeNode));
|
|
235
|
|
236 return list;
|
|
237 }
|
|
238
|
|
239 private static TypeExtension ParseType(XElement typeNode)
|
|
240 {
|
|
241 var ext = new TypeExtension();
|
|
242
|
|
243 foreach (var attr in typeNode.Attributes())
|
|
244 {
|
|
245 if (attr.Name.LocalName == AttrName.Name)
|
|
246 ext.Name = attr.Value;
|
|
247 else
|
|
248 ext.Attributes.Add(attr.Name.LocalName, attr.Value);
|
|
249 }
|
|
250
|
|
251 foreach (var node in typeNode.Elements())
|
|
252 {
|
|
253 if (node.Name.LocalName == NodeName.Member)
|
|
254 ext.Members.Add(ParseMember(node));
|
|
255 else
|
|
256 ext.Attributes.Add(ParseAttribute(node));
|
|
257 }
|
|
258
|
|
259 return ext;
|
|
260 }
|
|
261
|
|
262 private static MemberExtension ParseMember(XElement memberNode)
|
|
263 {
|
|
264 var ext = new MemberExtension();
|
|
265
|
|
266 foreach (var attr in memberNode.Attributes())
|
|
267 {
|
|
268 if (attr.Name.LocalName == AttrName.Name)
|
|
269 ext.Name = attr.Value;
|
|
270 else
|
|
271 ext.Attributes.Add(attr.Name.LocalName, attr.Value);
|
|
272 }
|
|
273
|
|
274 foreach (var node in memberNode.Elements())
|
|
275 ext.Attributes.Add(ParseAttribute(node));
|
|
276
|
|
277 return ext;
|
|
278 }
|
|
279
|
|
280 private static AttributeExtension ParseAttribute(XElement attributeNode)
|
|
281 {
|
|
282 var ext = new AttributeExtension
|
|
283 {
|
|
284 Name = attributeNode.Name.LocalName
|
|
285 };
|
|
286
|
|
287 ext.Values.Add(ValueName.Value, attributeNode.Value);
|
|
288
|
|
289 foreach (var attr in attributeNode.Attributes())
|
|
290 {
|
|
291 if (attr.Name.LocalName == ValueName.Type)
|
|
292 ext.Values.Add(ValueName.ValueType, attr.Value);
|
|
293 else
|
|
294 ext.Values.Add(attr.Name.LocalName, attr.Value);
|
|
295 }
|
|
296
|
|
297 foreach (var node in attributeNode.Elements())
|
|
298 ext.Attributes.Add(ParseAttribute(node));
|
|
299
|
|
300 return ext;
|
|
301 }
|
|
302
|
|
303 #endregion
|
|
304 }
|
|
305 }
|