Mercurial > pub > bltoolkit
comparison Tools/BLTgen/Program.cs @ 0:f990fcb411a9
Копия текущей версии из github
author | cin |
---|---|
date | Thu, 27 Mar 2014 21:46:09 +0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f990fcb411a9 |
---|---|
1 using System; | |
2 using System.ComponentModel; | |
3 using System.IO; | |
4 using System.Reflection; | |
5 using System.Text.RegularExpressions; | |
6 | |
7 using BLToolkit.Mapping; | |
8 using BLToolkit.Reflection; | |
9 using BLToolkit.TypeBuilder; | |
10 | |
11 namespace BLTgen | |
12 { | |
13 public class Arguments | |
14 { | |
15 [MapField(""), Description("source assembly location")] | |
16 public string SourceAssembly; | |
17 | |
18 [MapField("B"), Description("Base type names to include (default: none). Example: /B:*EntityBase;SomeNamespace.*Base")] | |
19 public string BaseTypes; | |
20 | |
21 [MapField("O"), Description("Output directory name (default: target assembly location). Example: /O:C:\\Temp")] | |
22 public string OutputDirectory; | |
23 | |
24 [MapField("I"), Description("Type names to include (default: all). Example: /I:*Accessor;SomeNamespace.*;OtherNamespace.*")] | |
25 public string Include; | |
26 | |
27 [MapField("X"), Description("Type names to exclude (default: none). Example: /X:SomeNamespace.SomeType")] | |
28 public string Exclude; | |
29 | |
30 [MapField("K"), Description("The key pair that is used to create a strong name signature for the output assembly (default: none). Example: /K:C:\\SomePath\\key.snk")] | |
31 public string KeyPairFile; | |
32 | |
33 [MapField("V"), Description("The version of the output assembly (same as source assembly by default). Example: /V:1.2.3.4")] | |
34 public string Version; | |
35 | |
36 [MapField("D"), Description("Detailed output (default: false). Example: /D")] | |
37 public string Debug; | |
38 } | |
39 | |
40 class Program | |
41 { | |
42 public static void Main(string[] args) | |
43 { | |
44 var parsedArgs = new Arguments(); | |
45 | |
46 Map.MapSourceToDestination(new StringListMapper(args), args, | |
47 Map.GetObjectMapper(typeof(Arguments)), parsedArgs); | |
48 | |
49 WriteBanner(); | |
50 | |
51 if (string.IsNullOrEmpty(parsedArgs.SourceAssembly)) | |
52 Usage(); | |
53 else | |
54 GenerateExtensionAssembly(parsedArgs); | |
55 } | |
56 | |
57 private static void GenerateExtensionAssembly(Arguments parsedArgs) | |
58 { | |
59 var verbose = parsedArgs.Debug != null; | |
60 var sourceAsm = Assembly.LoadFrom(parsedArgs.SourceAssembly); | |
61 var extensionAssemblyPath = GetOutputAssemblyLocation(sourceAsm.Location, parsedArgs.OutputDirectory); | |
62 var extensionAssemblyVersion = parsedArgs.Version != null? new Version(parsedArgs.Version): sourceAsm.GetName().Version; | |
63 var extensionAssemblyFolder = Path.GetDirectoryName(extensionAssemblyPath); | |
64 | |
65 if (verbose) | |
66 Console.WriteLine("{0} =>{1}{2}", sourceAsm.Location, Environment.NewLine, extensionAssemblyPath); | |
67 | |
68 if (!string.IsNullOrEmpty(extensionAssemblyFolder) && !Directory.Exists(extensionAssemblyFolder)) | |
69 Directory.CreateDirectory(extensionAssemblyFolder); | |
70 | |
71 var typesToProcess = sourceAsm.GetExportedTypes(); | |
72 | |
73 typesToProcess = FilterBaseTypes(typesToProcess, parsedArgs.BaseTypes); | |
74 typesToProcess = FilterTypes(typesToProcess, parsedArgs.Include, true); | |
75 typesToProcess = FilterTypes(typesToProcess, parsedArgs.Exclude, false); | |
76 | |
77 if (typesToProcess.Length > 0) | |
78 { | |
79 AppDomain.CurrentDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs args) | |
80 { | |
81 foreach (var asm in ((AppDomain)sender).GetAssemblies()) | |
82 { | |
83 if (string.Compare(asm.FullName, args.Name) == 0) | |
84 return asm; | |
85 } | |
86 | |
87 return null; | |
88 }; | |
89 | |
90 TypeFactory.SaveTypes = true; | |
91 TypeFactory.SetGlobalAssembly(extensionAssemblyPath, extensionAssemblyVersion, parsedArgs.KeyPairFile); | |
92 | |
93 foreach (var t in typesToProcess) | |
94 { | |
95 if (verbose) | |
96 Console.Write(GetFullTypeName(t)); | |
97 | |
98 // We cannot create accessors for generic definitions | |
99 // | |
100 if (t.IsGenericTypeDefinition) | |
101 { | |
102 if (verbose) | |
103 Console.WriteLine(" - skipping. Generic Definition"); | |
104 | |
105 continue; | |
106 } | |
107 | |
108 if (verbose) | |
109 Console.WriteLine(); | |
110 | |
111 try | |
112 { | |
113 TypeAccessor.GetAccessor(t); | |
114 } | |
115 catch (Exception e) | |
116 { | |
117 if (verbose) | |
118 Console.WriteLine(e); | |
119 } | |
120 } | |
121 | |
122 TypeFactory.SaveGlobalAssembly(); | |
123 } | |
124 else if (verbose) | |
125 Console.WriteLine("No types to process."); | |
126 } | |
127 | |
128 private static Type[] FilterBaseTypes(Type[] types, string pattern) | |
129 { | |
130 if (string.IsNullOrEmpty(pattern)) | |
131 return types; | |
132 | |
133 var re = new Regex("^" + Regex.Escape(pattern).Replace("\\*", ".*").Replace(";", "$|") + "$"); | |
134 | |
135 return Array.FindAll(types, delegate(Type t) | |
136 { | |
137 for (var bt = t.BaseType; bt != null; bt = bt.BaseType) | |
138 { | |
139 if (re.Match(GetFullTypeName(bt)).Success) | |
140 return true; | |
141 } | |
142 return false; | |
143 }); | |
144 } | |
145 | |
146 private static Type[] FilterTypes(Type[] types, string pattern, bool include) | |
147 { | |
148 if (string.IsNullOrEmpty(pattern)) | |
149 return types; | |
150 | |
151 var re = new Regex("^" + Regex.Escape(pattern).Replace("\\*", ".*").Replace(";", "$|") + "$"); | |
152 | |
153 return Array.FindAll(types, t => re.Match(GetFullTypeName(t)).Success == include); | |
154 } | |
155 | |
156 // System.Type.FullName may be null under some conditions. See | |
157 // http://blogs.msdn.com/haibo_luo/archive/2006/02/17/534480.aspx | |
158 // | |
159 private static string GetFullTypeName(Type t) | |
160 { | |
161 var fullName = t.FullName; | |
162 | |
163 if (fullName != null) | |
164 return fullName; | |
165 | |
166 if (t.DeclaringType != null) | |
167 return GetFullTypeName(t.DeclaringType) + "+" + t.Name; | |
168 | |
169 fullName = t.Namespace; | |
170 if (fullName != null) | |
171 fullName += "."; | |
172 | |
173 fullName += t.Name; | |
174 | |
175 return fullName; | |
176 } | |
177 | |
178 private static string GetOutputAssemblyLocation(string sourceAssembly, string outputDirectory) | |
179 { | |
180 if (string.IsNullOrEmpty(outputDirectory)) | |
181 outputDirectory = Path.GetDirectoryName(sourceAssembly); | |
182 | |
183 var fileName = Path.ChangeExtension(Path.GetFileName(sourceAssembly), "BLToolkitExtension.dll"); | |
184 return Path.Combine(Path.GetFullPath(outputDirectory), fileName); | |
185 } | |
186 | |
187 #region Usage | |
188 | |
189 private static void WriteBanner() | |
190 { | |
191 var asm = Assembly.GetExecutingAssembly(); | |
192 var descriptionAttribute = (AssemblyDescriptionAttribute) | |
193 Attribute.GetCustomAttribute(asm, typeof (AssemblyDescriptionAttribute)); | |
194 var copyrightAttribute = (AssemblyCopyrightAttribute) | |
195 Attribute.GetCustomAttribute(asm, typeof(AssemblyCopyrightAttribute)); | |
196 | |
197 Console.WriteLine("{0}, Version {1}", descriptionAttribute.Description, asm.GetName().Version); | |
198 Console.WriteLine(copyrightAttribute.Copyright); | |
199 Console.WriteLine(); | |
200 } | |
201 | |
202 private static string ExecutableName | |
203 { | |
204 get { return Path.GetFileName(new Uri(Assembly.GetEntryAssembly().EscapedCodeBase).LocalPath); } | |
205 } | |
206 | |
207 private static string GetDescription(MemberMapper mm) | |
208 { | |
209 var desc = mm.MemberAccessor.GetAttribute<DescriptionAttribute>(); | |
210 | |
211 return (null != desc) ? desc.Description : string.Empty; | |
212 } | |
213 | |
214 private static void Usage() | |
215 { | |
216 var om = Map.GetObjectMapper(typeof(Arguments)); | |
217 | |
218 Console.Write("Usage: {0}", ExecutableName); | |
219 | |
220 foreach (MemberMapper mm in om) | |
221 { | |
222 if (0 == mm.Name.Length) | |
223 Console.Write(" <{0}>", GetDescription(mm)); | |
224 else | |
225 Console.Write(" /{0}:", mm.Name); | |
226 } | |
227 | |
228 Console.WriteLine(); | |
229 Console.WriteLine("Options:"); | |
230 | |
231 foreach (MemberMapper mm in om) | |
232 { | |
233 if (0 != mm.Name.Length) | |
234 Console.WriteLine("\t{0}: {1}", mm.Name, GetDescription(mm)); | |
235 } | |
236 | |
237 Console.WriteLine(); | |
238 } | |
239 | |
240 #endregion | |
241 } | |
242 } |