Mercurial > pub > bltoolkit
diff Source/Reflection/Emit/AssemblyBuilderHelper.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/Source/Reflection/Emit/AssemblyBuilderHelper.cs Thu Mar 27 21:46:09 2014 +0400 @@ -0,0 +1,315 @@ +using System; +using System.Configuration.Assemblies; +using System.Reflection; +using System.Reflection.Emit; +using System.Security; +using System.Threading; + +namespace BLToolkit.Reflection.Emit +{ + /// <summary> + /// A wrapper around the <see cref="AssemblyBuilder"/> and <see cref="ModuleBuilder"/> classes. + /// </summary> + /// <include file="Examples.CS.xml" path='examples/emit[@name="Emit"]/*' /> + /// <include file="Examples.VB.xml" path='examples/emit[@name="Emit"]/*' /> + /// <seealso cref="System.Reflection.Emit.AssemblyBuilder">AssemblyBuilder Class</seealso> + /// <seealso cref="System.Reflection.Emit.ModuleBuilder">ModuleBuilder Class</seealso> + public class AssemblyBuilderHelper + { + /// <summary> + /// Initializes a new instance of the <see cref="AssemblyBuilderHelper"/> class + /// with the specified parameters. + /// </summary> + /// <param name="path">The path where the assembly will be saved.</param> + public AssemblyBuilderHelper(string path) : this(path, null, null) + { + } + + /// <summary> + /// Initializes a new instance of the <see cref="AssemblyBuilderHelper"/> class + /// with the specified parameters. + /// </summary> + /// <param name="path">The path where the assembly will be saved.</param> + /// <param name="version">The assembly version.</param> + /// <param name="keyFile">The key pair file to sign the assembly.</param> + public AssemblyBuilderHelper(string path, Version version, string keyFile) + { + if (path == null) throw new ArgumentNullException("path"); + + var idx = path.IndexOf(','); + + if (idx > 0) + { + path = path.Substring(0, idx); + + if (path.Length >= 200) + { + idx = path.IndexOf('`'); + + if (idx > 0) + { + var idx2 = path.LastIndexOf('.'); + + if (idx2 > 0 && idx2 > idx) + path = path.Substring(0, idx + 1) + path.Substring(idx2 + 1); + } + } + } + + path = path.Replace("+", ".").Replace("<", "_").Replace(">", "_"); + + if (path.Length >= 260) + { + path = path.Substring(0, 248); + + for (var i = 0; i < int.MaxValue; i++) + { + var newPath = string.Format("{0}_{1:0000}.dll", path, i); + + if (!System.IO.File.Exists(newPath)) + { + path = newPath; + break; + } + } + } + + var assemblyName = System.IO.Path.GetFileNameWithoutExtension(path); + var assemblyDir = System.IO.Path.GetDirectoryName(path); + + Path = path; + _assemblyName.Name = assemblyName; + + if (version != null) + _assemblyName.Version = version; + +#if !SILVERLIGHT + + if (!string.IsNullOrEmpty(keyFile)) + { + _assemblyName.Flags |= AssemblyNameFlags.PublicKey; + _assemblyName.KeyPair = new StrongNameKeyPair(System.IO.File.OpenRead(keyFile)); + _assemblyName.HashAlgorithm = AssemblyHashAlgorithm.SHA1; + } + +#endif + +#if DEBUG + _assemblyName.Flags |= AssemblyNameFlags.EnableJITcompileTracking; +#else + _assemblyName.Flags |= AssemblyNameFlags.EnableJITcompileOptimizer; +#endif + + _createAssemblyBuilder = _ => + { +#if SILVERLIGHT + _assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(_assemblyName, AssemblyBuilderAccess.Run); +#else + _assemblyBuilder = + string.IsNullOrEmpty(assemblyDir)? + Thread.GetDomain().DefineDynamicAssembly(_assemblyName, AssemblyBuilderAccess.RunAndSave): + Thread.GetDomain().DefineDynamicAssembly(_assemblyName, AssemblyBuilderAccess.RunAndSave, assemblyDir); +#endif + + _assemblyBuilder.SetCustomAttribute(BLToolkitAttribute); + +#if !SILVERLIGHT + + _assemblyBuilder.SetCustomAttribute( + new CustomAttributeBuilder( + typeof(AllowPartiallyTrustedCallersAttribute) + .GetConstructor(Type.EmptyTypes), + new object[0])); + +#endif + }; + } + + /// <summary> + /// Gets the path where the assembly will be saved. + /// </summary> + public string Path { get; private set; } + + private readonly AssemblyName _assemblyName = new AssemblyName(); + /// <summary> + /// Gets AssemblyName. + /// </summary> + public AssemblyName AssemblyName + { + get { return _assemblyName; } + } + + readonly Action<int> _createAssemblyBuilder; + + AssemblyBuilder _assemblyBuilder; + /// <summary> + /// Gets AssemblyBuilder. + /// </summary> + public AssemblyBuilder AssemblyBuilder + { + get + { + if (_assemblyBuilder == null) + _createAssemblyBuilder(0); + return _assemblyBuilder; + } + } + + /// <summary> + /// Gets the path where the assembly will be saved. + /// </summary> + public string ModulePath + { + get { return System.IO.Path.GetFileName(Path); } + } + + private ModuleBuilder _moduleBuilder; + /// <summary> + /// Gets ModuleBuilder. + /// </summary> + public ModuleBuilder ModuleBuilder + { + get + { + if (_moduleBuilder == null) + { + _moduleBuilder = AssemblyBuilder.DefineDynamicModule(ModulePath); + _moduleBuilder.SetCustomAttribute(BLToolkitAttribute); + + } + + return _moduleBuilder; + } + } + + private CustomAttributeBuilder _blToolkitAttribute; + /// <summary> + /// Retrieves a cached instance of <see cref="BLToolkit.TypeBuilder.BLToolkitGeneratedAttribute"/> builder. + /// </summary> + public CustomAttributeBuilder BLToolkitAttribute + { + get + { + if (_blToolkitAttribute == null) + { + var at = typeof(TypeBuilder.BLToolkitGeneratedAttribute); + var ci = at.GetConstructor(Type.EmptyTypes); + + _blToolkitAttribute = new CustomAttributeBuilder(ci, new object[0]); + } + + return _blToolkitAttribute; + } + } + + /// <summary> + /// Converts the supplied <see cref="AssemblyBuilderHelper"/> to a <see cref="AssemblyBuilder"/>. + /// </summary> + /// <param name="assemblyBuilder">The <see cref="AssemblyBuilderHelper"/>.</param> + /// <returns>An <see cref="AssemblyBuilder"/>.</returns> + public static implicit operator AssemblyBuilder(AssemblyBuilderHelper assemblyBuilder) + { + if (assemblyBuilder == null) throw new ArgumentNullException("assemblyBuilder"); + + return assemblyBuilder.AssemblyBuilder; + } + + /// <summary> + /// Converts the supplied <see cref="AssemblyBuilderHelper"/> to a <see cref="ModuleBuilder"/>. + /// </summary> + /// <param name="assemblyBuilder">The <see cref="AssemblyBuilderHelper"/>.</param> + /// <returns>A <see cref="ModuleBuilder"/>.</returns> + public static implicit operator ModuleBuilder(AssemblyBuilderHelper assemblyBuilder) + { + if (assemblyBuilder == null) throw new ArgumentNullException("assemblyBuilder"); + + return assemblyBuilder.ModuleBuilder; + } + + /// <summary> + /// Saves this dynamic assembly to disk. + /// </summary> + public void Save() + { +#if !SILVERLIGHT + + if (_assemblyBuilder != null) + _assemblyBuilder.Save(ModulePath); + +#endif + } + + #region DefineType Overrides + + /// <summary> + /// Constructs a <see cref="TypeBuilderHelper"/> for a type with the specified name. + /// </summary> + /// <param name="name">The full path of the type.</param> + /// <returns>Returns the created <see cref="TypeBuilderHelper"/>.</returns> + /// <seealso cref="System.Reflection.Emit.ModuleBuilder.DefineType(string)">ModuleBuilder.DefineType Method</seealso> + public TypeBuilderHelper DefineType(string name) + { + return new TypeBuilderHelper(this, ModuleBuilder.DefineType(name)); + } + + /// <summary> + /// Constructs a <see cref="TypeBuilderHelper"/> for a type with the specified name and base type. + /// </summary> + /// <param name="name">The full path of the type.</param> + /// <param name="parent">The Type that the defined type extends.</param> + /// <returns>Returns the created <see cref="TypeBuilderHelper"/>.</returns> + /// <seealso cref="System.Reflection.Emit.ModuleBuilder.DefineType(string,TypeAttributes,Type)">ModuleBuilder.DefineType Method</seealso> + public TypeBuilderHelper DefineType(string name, Type parent) + { + return new TypeBuilderHelper(this, ModuleBuilder.DefineType(name, TypeAttributes.Public, parent)); + } + + /// <summary> + /// Constructs a <see cref="TypeBuilderHelper"/> for a type with the specified name, its attributes, and base type. + /// </summary> + /// <param name="name">The full path of the type.</param> + /// <param name="attrs">The attribute to be associated with the type.</param> + /// <param name="parent">The Type that the defined type extends.</param> + /// <returns>Returns the created <see cref="TypeBuilderHelper"/>.</returns> + /// <seealso cref="System.Reflection.Emit.ModuleBuilder.DefineType(string,TypeAttributes,Type)">ModuleBuilder.DefineType Method</seealso> + public TypeBuilderHelper DefineType(string name, TypeAttributes attrs, Type parent) + { + return new TypeBuilderHelper(this, ModuleBuilder.DefineType(name, attrs, parent)); + } + + /// <summary> + /// Constructs a <see cref="TypeBuilderHelper"/> for a type with the specified name, base type, + /// and the interfaces that the defined type implements. + /// </summary> + /// <param name="name">The full path of the type.</param> + /// <param name="parent">The Type that the defined type extends.</param> + /// <param name="interfaces">The list of interfaces that the type implements.</param> + /// <returns>Returns the created <see cref="TypeBuilderHelper"/>.</returns> + /// <seealso cref="System.Reflection.Emit.ModuleBuilder.DefineType(string,TypeAttributes,Type,Type[])">ModuleBuilder.DefineType Method</seealso> + public TypeBuilderHelper DefineType(string name, Type parent, params Type[] interfaces) + { + return new TypeBuilderHelper( + this, + ModuleBuilder.DefineType(name, TypeAttributes.Public, parent, interfaces)); + } + + /// <summary> + /// Constructs a <see cref="TypeBuilderHelper"/> for a type with the specified name, its attributes, base type, + /// and the interfaces that the defined type implements. + /// </summary> + /// <param name="name">The full path of the type.</param> + /// <param name="attrs">The attribute to be associated with the type.</param> + /// <param name="parent">The Type that the defined type extends.</param> + /// <param name="interfaces">The list of interfaces that the type implements.</param> + /// <returns>Returns the created <see cref="TypeBuilderHelper"/>.</returns> + /// <seealso cref="System.Reflection.Emit.ModuleBuilder.DefineType(string,TypeAttributes,Type,Type[])">ModuleBuilder.DefineType Method</seealso> + public TypeBuilderHelper DefineType(string name, TypeAttributes attrs, Type parent, params Type[] interfaces) + { + return new TypeBuilderHelper( + this, + ModuleBuilder.DefineType(name, attrs, parent, interfaces)); + } + + #endregion + } +}