0
|
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 }
|