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 }