Mercurial > pub > bltoolkit
diff Tools/BLTgen/Program.cs @ 0:f990fcb411a9
Копия текущей версии из github
author | cin |
---|---|
date | Thu, 27 Mar 2014 21:46:09 +0400 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Tools/BLTgen/Program.cs Thu Mar 27 21:46:09 2014 +0400 @@ -0,0 +1,242 @@ +using System; +using System.ComponentModel; +using System.IO; +using System.Reflection; +using System.Text.RegularExpressions; + +using BLToolkit.Mapping; +using BLToolkit.Reflection; +using BLToolkit.TypeBuilder; + +namespace BLTgen +{ + public class Arguments + { + [MapField(""), Description("source assembly location")] + public string SourceAssembly; + + [MapField("B"), Description("Base type names to include (default: none). Example: /B:*EntityBase;SomeNamespace.*Base")] + public string BaseTypes; + + [MapField("O"), Description("Output directory name (default: target assembly location). Example: /O:C:\\Temp")] + public string OutputDirectory; + + [MapField("I"), Description("Type names to include (default: all). Example: /I:*Accessor;SomeNamespace.*;OtherNamespace.*")] + public string Include; + + [MapField("X"), Description("Type names to exclude (default: none). Example: /X:SomeNamespace.SomeType")] + public string Exclude; + + [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")] + public string KeyPairFile; + + [MapField("V"), Description("The version of the output assembly (same as source assembly by default). Example: /V:1.2.3.4")] + public string Version; + + [MapField("D"), Description("Detailed output (default: false). Example: /D")] + public string Debug; + } + + class Program + { + public static void Main(string[] args) + { + var parsedArgs = new Arguments(); + + Map.MapSourceToDestination(new StringListMapper(args), args, + Map.GetObjectMapper(typeof(Arguments)), parsedArgs); + + WriteBanner(); + + if (string.IsNullOrEmpty(parsedArgs.SourceAssembly)) + Usage(); + else + GenerateExtensionAssembly(parsedArgs); + } + + private static void GenerateExtensionAssembly(Arguments parsedArgs) + { + var verbose = parsedArgs.Debug != null; + var sourceAsm = Assembly.LoadFrom(parsedArgs.SourceAssembly); + var extensionAssemblyPath = GetOutputAssemblyLocation(sourceAsm.Location, parsedArgs.OutputDirectory); + var extensionAssemblyVersion = parsedArgs.Version != null? new Version(parsedArgs.Version): sourceAsm.GetName().Version; + var extensionAssemblyFolder = Path.GetDirectoryName(extensionAssemblyPath); + + if (verbose) + Console.WriteLine("{0} =>{1}{2}", sourceAsm.Location, Environment.NewLine, extensionAssemblyPath); + + if (!string.IsNullOrEmpty(extensionAssemblyFolder) && !Directory.Exists(extensionAssemblyFolder)) + Directory.CreateDirectory(extensionAssemblyFolder); + + var typesToProcess = sourceAsm.GetExportedTypes(); + + typesToProcess = FilterBaseTypes(typesToProcess, parsedArgs.BaseTypes); + typesToProcess = FilterTypes(typesToProcess, parsedArgs.Include, true); + typesToProcess = FilterTypes(typesToProcess, parsedArgs.Exclude, false); + + if (typesToProcess.Length > 0) + { + AppDomain.CurrentDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs args) + { + foreach (var asm in ((AppDomain)sender).GetAssemblies()) + { + if (string.Compare(asm.FullName, args.Name) == 0) + return asm; + } + + return null; + }; + + TypeFactory.SaveTypes = true; + TypeFactory.SetGlobalAssembly(extensionAssemblyPath, extensionAssemblyVersion, parsedArgs.KeyPairFile); + + foreach (var t in typesToProcess) + { + if (verbose) + Console.Write(GetFullTypeName(t)); + + // We cannot create accessors for generic definitions + // + if (t.IsGenericTypeDefinition) + { + if (verbose) + Console.WriteLine(" - skipping. Generic Definition"); + + continue; + } + + if (verbose) + Console.WriteLine(); + + try + { + TypeAccessor.GetAccessor(t); + } + catch (Exception e) + { + if (verbose) + Console.WriteLine(e); + } + } + + TypeFactory.SaveGlobalAssembly(); + } + else if (verbose) + Console.WriteLine("No types to process."); + } + + private static Type[] FilterBaseTypes(Type[] types, string pattern) + { + if (string.IsNullOrEmpty(pattern)) + return types; + + var re = new Regex("^" + Regex.Escape(pattern).Replace("\\*", ".*").Replace(";", "$|") + "$"); + + return Array.FindAll(types, delegate(Type t) + { + for (var bt = t.BaseType; bt != null; bt = bt.BaseType) + { + if (re.Match(GetFullTypeName(bt)).Success) + return true; + } + return false; + }); + } + + private static Type[] FilterTypes(Type[] types, string pattern, bool include) + { + if (string.IsNullOrEmpty(pattern)) + return types; + + var re = new Regex("^" + Regex.Escape(pattern).Replace("\\*", ".*").Replace(";", "$|") + "$"); + + return Array.FindAll(types, t => re.Match(GetFullTypeName(t)).Success == include); + } + + // System.Type.FullName may be null under some conditions. See + // http://blogs.msdn.com/haibo_luo/archive/2006/02/17/534480.aspx + // + private static string GetFullTypeName(Type t) + { + var fullName = t.FullName; + + if (fullName != null) + return fullName; + + if (t.DeclaringType != null) + return GetFullTypeName(t.DeclaringType) + "+" + t.Name; + + fullName = t.Namespace; + if (fullName != null) + fullName += "."; + + fullName += t.Name; + + return fullName; + } + + private static string GetOutputAssemblyLocation(string sourceAssembly, string outputDirectory) + { + if (string.IsNullOrEmpty(outputDirectory)) + outputDirectory = Path.GetDirectoryName(sourceAssembly); + + var fileName = Path.ChangeExtension(Path.GetFileName(sourceAssembly), "BLToolkitExtension.dll"); + return Path.Combine(Path.GetFullPath(outputDirectory), fileName); + } + + #region Usage + + private static void WriteBanner() + { + var asm = Assembly.GetExecutingAssembly(); + var descriptionAttribute = (AssemblyDescriptionAttribute) + Attribute.GetCustomAttribute(asm, typeof (AssemblyDescriptionAttribute)); + var copyrightAttribute = (AssemblyCopyrightAttribute) + Attribute.GetCustomAttribute(asm, typeof(AssemblyCopyrightAttribute)); + + Console.WriteLine("{0}, Version {1}", descriptionAttribute.Description, asm.GetName().Version); + Console.WriteLine(copyrightAttribute.Copyright); + Console.WriteLine(); + } + + private static string ExecutableName + { + get { return Path.GetFileName(new Uri(Assembly.GetEntryAssembly().EscapedCodeBase).LocalPath); } + } + + private static string GetDescription(MemberMapper mm) + { + var desc = mm.MemberAccessor.GetAttribute<DescriptionAttribute>(); + + return (null != desc) ? desc.Description : string.Empty; + } + + private static void Usage() + { + var om = Map.GetObjectMapper(typeof(Arguments)); + + Console.Write("Usage: {0}", ExecutableName); + + foreach (MemberMapper mm in om) + { + if (0 == mm.Name.Length) + Console.Write(" <{0}>", GetDescription(mm)); + else + Console.Write(" /{0}:", mm.Name); + } + + Console.WriteLine(); + Console.WriteLine("Options:"); + + foreach (MemberMapper mm in om) + { + if (0 != mm.Name.Length) + Console.WriteLine("\t{0}: {1}", mm.Name, GetDescription(mm)); + } + + Console.WriteLine(); + } + + #endregion + } +}