//******************************************************************************************************
// AssemblyInfo.cs - Gbtc
//
// Copyright © 2012, Grid Protection Alliance. All Rights Reserved.
//
// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
// the NOTICE file distributed with this work for additional information regarding copyright ownership.
// The GPA licenses this file to you under the MIT License (MIT), the "License"; you may
// not use this file except in compliance with the License. You may obtain a copy of the License at:
//
// http://www.opensource.org/licenses/MIT
//
// Unless agreed to in writing, the subject software distributed under the License is distributed on an
// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
// License for the specific language governing permissions and limitations.
//
// Code Modification History:
// ----------------------------------------------------------------------------------------------------
// 04/29/2005 - Pinal C. Patel
// Generated original version of source code.
// 12/29/2005 - Pinal C. Patel
// Migrated 2.0 version of source code from 1.1 source (GSF.Shared.Assembly).
// 12/12/2007 - Darrell Zuercher
// Edited Code Comments.
// 09/08/2008 - J. Ritchie Carroll
// Converted to C# as AssemblyInformation.
// 09/14/2009 - Stephen C. Wills
// Added new header and license agreement.
// 10/21/2009 - Pinal C. Patel
// Added error checking to assembly attribute properties.
// 09/28/2010 - Pinal C. Patel
// Modified EntryAssembly to perform a reflection only load of the currently executing process
// to deal with entry assembly not being available in non-default application domains.
// Changed GetCustomAttribute() to return CustomAttributeData instead of Object to deal with
// possible reflection only load being performed in EntryAssembly.
// Removed debuggable property since it was not very useful and added complexity when extracting.
// 09/21/2011 - J. Ritchie Carroll
// Added Mono implementation exception regions.
// 12/14/2012 - Starlynn Danyelle Gilliam
// Modified Header.
//
//******************************************************************************************************
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.InteropServices;
using System.Security;
using GSF.IO;
namespace GSF.Reflection
{
///
/// Represents a common information provider for an assembly.
///
public class AssemblyInfo
{
#region [ Members ]
// Fields
private readonly Assembly m_assemblyInstance;
#endregion
#region [ Constructors ]
/// Initializes a new instance of the class.
/// An object.
public AssemblyInfo(Assembly assemblyInstance)
{
m_assemblyInstance = assemblyInstance;
}
#endregion
#region [ Properties ]
///
/// Gets the underlying being represented by this object.
///
public Assembly Assembly
{
get
{
return m_assemblyInstance;
}
}
///
/// Gets the title information of the .
///
public string Title
{
get
{
CustomAttributeData attribute = GetCustomAttribute(typeof(AssemblyTitleAttribute));
if ((object)attribute == null)
return string.Empty;
return (string)attribute.ConstructorArguments[0].Value;
}
}
///
/// Gets the description information of the .
///
public string Description
{
get
{
CustomAttributeData attribute = GetCustomAttribute(typeof(AssemblyDescriptionAttribute));
if ((object)attribute == null)
return string.Empty;
return (string)attribute.ConstructorArguments[0].Value;
}
}
///
/// Gets the company name information of the .
///
public string Company
{
get
{
CustomAttributeData attribute = GetCustomAttribute(typeof(AssemblyCompanyAttribute));
if ((object)attribute == null)
return string.Empty;
return (string)attribute.ConstructorArguments[0].Value;
}
}
///
/// Gets the product name information of the .
///
public string Product
{
get
{
CustomAttributeData attribute = GetCustomAttribute(typeof(AssemblyProductAttribute));
if ((object)attribute == null)
return string.Empty;
return (string)attribute.ConstructorArguments[0].Value;
}
}
///
/// Gets the copyright information of the .
///
public string Copyright
{
get
{
CustomAttributeData attribute = GetCustomAttribute(typeof(AssemblyCopyrightAttribute));
if ((object)attribute == null)
return string.Empty;
return (string)attribute.ConstructorArguments[0].Value;
}
}
///
/// Gets the trademark information of the .
///
public string Trademark
{
get
{
CustomAttributeData attribute = GetCustomAttribute(typeof(AssemblyTrademarkAttribute));
if ((object)attribute == null)
return string.Empty;
return (string)attribute.ConstructorArguments[0].Value;
}
}
///
/// Gets the configuration information of the .
///
public string Configuration
{
get
{
CustomAttributeData attribute = GetCustomAttribute(typeof(AssemblyConfigurationAttribute));
if ((object)attribute == null)
return string.Empty;
return (string)attribute.ConstructorArguments[0].Value;
}
}
///
/// Gets a boolean value indicating if the has been built as delay-signed.
///
public bool DelaySign
{
get
{
CustomAttributeData attribute = GetCustomAttribute(typeof(AssemblyDelaySignAttribute));
if ((object)attribute == null)
return false;
return (bool)attribute.ConstructorArguments[0].Value;
}
}
///
/// Gets the version information of the .
///
public string InformationalVersion
{
get
{
CustomAttributeData attribute = GetCustomAttribute(typeof(AssemblyInformationalVersionAttribute));
if ((object)attribute == null)
return string.Empty;
return (string)attribute.ConstructorArguments[0].Value;
}
}
///
/// Gets the name of the file containing the key pair used to generate a strong name for the attributed .
///
public string KeyFile
{
get
{
CustomAttributeData attribute = GetCustomAttribute(typeof(AssemblyKeyFileAttribute));
if ((object)attribute == null)
return string.Empty;
return (string)attribute.ConstructorArguments[0].Value;
}
}
///
/// Gets the culture name of the .
///
public string CultureName
{
get
{
CustomAttributeData attribute = GetCustomAttribute(typeof(NeutralResourcesLanguageAttribute));
if ((object)attribute == null)
return string.Empty;
return (string)attribute.ConstructorArguments[0].Value;
}
}
///
/// Gets the assembly version used to instruct the System.Resources.ResourceManager to ask for a particular
/// version of a satellite assembly to simplify updates of the main assembly of an application.
///
public string SatelliteContractVersion
{
get
{
CustomAttributeData attribute = GetCustomAttribute(typeof(SatelliteContractVersionAttribute));
if ((object)attribute == null)
return string.Empty;
return (string)attribute.ConstructorArguments[0].Value;
}
}
///
/// Gets the string representing the assembly version used to indicate to a COM client that all classes
/// in the current version of the assembly are compatible with classes in an earlier version of the assembly.
///
public string ComCompatibleVersion
{
get
{
CustomAttributeData attribute = GetCustomAttribute(typeof(ComCompatibleVersionAttribute));
if ((object)attribute == null)
return string.Empty;
return attribute.ConstructorArguments[0].Value + "." +
attribute.ConstructorArguments[1].Value + "." +
attribute.ConstructorArguments[2].Value + "." +
attribute.ConstructorArguments[3].Value;
}
}
///
/// Gets a boolean value indicating if the is exposed to COM.
///
public bool ComVisible
{
get
{
CustomAttributeData attribute = GetCustomAttribute(typeof(ComVisibleAttribute));
if ((object)attribute == null)
return false;
return (bool)attribute.ConstructorArguments[0].Value;
}
}
///
/// Gets a boolean value indicating if the was built in debug mode.
///
public bool Debuggable
{
get
{
DebuggableAttribute attribute = m_assemblyInstance.GetCustomAttributes().FirstOrDefault();
return (object)attribute != null && attribute.IsJITOptimizerDisabled;
}
}
///
/// Gets the GUID that is used as an ID if the is exposed to COM.
///
public string Guid
{
get
{
CustomAttributeData attribute = GetCustomAttribute(typeof(GuidAttribute));
if ((object)attribute == null)
return string.Empty;
return (string)attribute.ConstructorArguments[0].Value;
}
}
///
/// Gets the string representing the version number in MajorVersion.MinorVersion format.
///
public string TypeLibVersion
{
get
{
CustomAttributeData attribute = GetCustomAttribute(typeof(TypeLibVersionAttribute));
if ((object)attribute == null)
return string.Empty;
return attribute.ConstructorArguments[0].Value + "." +
attribute.ConstructorArguments[1].Value;
}
}
///
/// Gets a boolean value indicating whether the is CLS-compliant.
///
public bool CLSCompliant
{
get
{
CustomAttributeData attribute = GetCustomAttribute(typeof(CLSCompliantAttribute));
if ((object)attribute == null)
return false;
return (bool)attribute.ConstructorArguments[0].Value;
}
}
///
/// Gets the path or UNC location of the loaded file that contains the manifest.
///
public string Location
{
get
{
return m_assemblyInstance.Location;
}
}
///
/// Gets the location of the as specified originally.
///
public string CodeBase
{
get
{
return m_assemblyInstance.CodeBase.Replace("file:///", "");
}
}
///
/// Gets the display name of the .
///
public string FullName
{
get
{
return m_assemblyInstance.FullName;
}
}
///
/// Gets the simple, unencrypted name of the .
///
public string Name
{
get
{
return m_assemblyInstance.GetName().Name;
}
}
///
/// Gets the major, minor, revision, and build numbers of the .
///
public Version Version
{
get
{
return m_assemblyInstance.GetName().Version;
}
}
///
/// Gets the string representing the version of the common language runtime (CLR) saved in the file
/// containing the manifest.
///
public string ImageRuntimeVersion
{
get
{
return m_assemblyInstance.ImageRuntimeVersion;
}
}
///
/// Gets a boolean value indicating whether the was loaded from the global assembly cache.
///
public bool GACLoaded
{
get
{
return m_assemblyInstance.GlobalAssemblyCache;
}
}
///
/// Gets the date and time when the was built.
///
public DateTime BuildDate
{
get
{
// ReSharper disable once AssignNullToNotNullAttribute
return File.GetLastWriteTime(m_assemblyInstance.Location);
}
}
///
/// Gets the root namespace of the .
///
public string RootNamespace
{
get
{
return m_assemblyInstance.GetExportedTypes()[0].Namespace;
}
}
#endregion
#region [ Methods ]
///
/// Gets a collection of assembly attributes exposed by the assembly.
///
/// A System.Specialized.KeyValueCollection of assembly attributes.
public NameValueCollection GetAttributes()
{
NameValueCollection assemblyAttributes = new NameValueCollection();
//Add some values that are not in AssemblyInfo.
assemblyAttributes.Add("Full Name", FullName);
assemblyAttributes.Add("Name", Name);
assemblyAttributes.Add("Version", Version.ToString());
assemblyAttributes.Add("Image Runtime Version", ImageRuntimeVersion);
assemblyAttributes.Add("Build Date", BuildDate.ToString());
assemblyAttributes.Add("Location", Location);
assemblyAttributes.Add("Code Base", CodeBase);
assemblyAttributes.Add("GAC Loaded", GACLoaded.ToString());
//Add all attributes available from AssemblyInfo.
assemblyAttributes.Add("Title", Title);
assemblyAttributes.Add("Description", Description);
assemblyAttributes.Add("Company", Company);
assemblyAttributes.Add("Product", Product);
assemblyAttributes.Add("Copyright", Copyright);
assemblyAttributes.Add("Trademark", Trademark);
assemblyAttributes.Add("Configuration", Configuration);
assemblyAttributes.Add("Delay Sign", DelaySign.ToString());
assemblyAttributes.Add("Informational Version", InformationalVersion);
assemblyAttributes.Add("Key File", KeyFile);
assemblyAttributes.Add("Culture Name", CultureName);
assemblyAttributes.Add("Satellite Contract Version", SatelliteContractVersion);
assemblyAttributes.Add("Com Compatible Version", ComCompatibleVersion);
assemblyAttributes.Add("Com Visible", ComVisible.ToString());
assemblyAttributes.Add("Guid", Guid);
assemblyAttributes.Add("Type Lib Version", TypeLibVersion);
assemblyAttributes.Add("CLS Compliant", CLSCompliant.ToString());
return assemblyAttributes;
}
///
/// Gets the specified assembly attribute if it is exposed by the assembly.
///
/// Type of the attribute to get.
/// The requested assembly attribute if it exists; otherwise null.
///
/// This method always returns null under Mono deployments.
///
public CustomAttributeData GetCustomAttribute(Type attributeType)
{
#if MONO
// TODO: Validate that these functions still do not work under Mono - they make actually return expected results with new Mono updates
return null;
#else
//Returns the requested assembly attribute.
return m_assemblyInstance.GetCustomAttributesData().FirstOrDefault(assemblyAttribute => assemblyAttribute.Constructor.DeclaringType == attributeType);
#endif
}
///
/// Gets the specified embedded resource from the assembly.
///
/// The full name (including the namespace) of the embedded resource to get.
/// The embedded resource.
public Stream GetEmbeddedResource(string resourceName)
{
//Extracts and returns the requested embedded resource.
return m_assemblyInstance.GetEmbeddedResource(resourceName);
}
#endregion
#region [ Static ]
// Static Fields
private static AssemblyInfo s_callingAssembly;
private static AssemblyInfo s_entryAssembly;
private static AssemblyInfo s_executingAssembly;
private static Dictionary s_assemblyCache;
private static bool s_addedResolver;
private static readonly Dictionary s_typeCache = new Dictionary();
private static readonly AppDomainTypeLookup s_typeLookup = new AppDomainTypeLookup();
// Static Properties
///
/// Finds the specified searching through all loaded assemblies.
///
/// Fully qualified type name.
/// The found; otherwise null.
public static Type FindType(string typeName)
{
lock (s_typeCache)
{
Type result;
if (s_typeLookup.HasChanged)
{
foreach (Type type in s_typeLookup.FindTypes())
s_typeCache[type.FullName] = type;
}
s_typeCache.TryGetValue(typeName, out result);
return result;
}
}
///
/// Gets the object of the assembly that invoked the currently executing method.
///
public static AssemblyInfo CallingAssembly
{
get
{
if ((object)s_callingAssembly == null)
{
// We have to find the calling assembly of the caller
StackTrace trace = new StackTrace();
Assembly caller = Assembly.GetCallingAssembly();
Assembly current = Assembly.GetExecutingAssembly();
StackFrame[] stackFrames = trace.GetFrames();
if ((object)stackFrames != null)
{
foreach (StackFrame frame in stackFrames)
{
if ((object)frame != null)
{
MethodBase method = frame.GetMethod();
if ((object)method != null && (object)method.DeclaringType != null)
{
Assembly assembly = Assembly.GetAssembly(method.DeclaringType);
if (assembly != caller && assembly != current)
{
// Assembly is neither the current assembly or the calling assembly
s_callingAssembly = new AssemblyInfo(assembly);
break;
}
}
}
}
}
}
return s_callingAssembly;
}
}
///
/// Gets the object of the process executable in the default application domain.
///
public static AssemblyInfo EntryAssembly
{
get
{
if ((object)s_entryAssembly == null)
{
Assembly entryAssembly = Assembly.GetEntryAssembly();
if ((object)entryAssembly == null)
entryAssembly = Assembly.ReflectionOnlyLoadFrom(Process.GetCurrentProcess().MainModule.FileName);
s_entryAssembly = new AssemblyInfo(entryAssembly);
}
return s_entryAssembly;
}
}
///
/// Gets the object of the assembly that contains the code that is currently executing.
///
public static AssemblyInfo ExecutingAssembly
{
get
{
// Caller's assembly will be the executing assembly for the caller
if ((object)s_executingAssembly == null)
s_executingAssembly = new AssemblyInfo(Assembly.GetCallingAssembly());
return s_executingAssembly;
}
}
// Static Methods
///
/// Loads the specified assembly that is embedded as a resource in the assembly.
///
/// Name of the assembly to load.
/// Note that this function cannot be used to load GSF.Core itself, since this is where function resides.
[SecurityCritical]
public static void LoadAssemblyFromResource(string assemblyName)
{
// Hooks into assembly resolve event for current domain so it can load assembly from embedded resource
if (!s_addedResolver)
{
AppDomain.CurrentDomain.AssemblyResolve += ResolveAssemblyFromResource;
s_addedResolver = true;
}
// Loads the assembly (this will invoke event that will resolve assembly from resource)
AppDomain.CurrentDomain.Load(assemblyName);
}
private static Assembly ResolveAssemblyFromResource(object sender, ResolveEventArgs e)
{
Assembly resourceAssembly;
string shortName = e.Name.Split(',')[0];
if ((object)s_assemblyCache == null)
s_assemblyCache = new Dictionary();
resourceAssembly = s_assemblyCache[shortName];
if ((object)resourceAssembly == null)
{
// Loops through all of the resources in the executing assembly
foreach (string name in Assembly.GetEntryAssembly().GetManifestResourceNames())
{
// Sees if the embedded resource name matches the assembly it is trying to load.
if (string.Compare(FilePath.GetFileNameWithoutExtension(name), EntryAssembly.RootNamespace + "." + shortName, StringComparison.OrdinalIgnoreCase) == 0)
{
// If so, loads embedded resource assembly into a binary buffer
Stream resourceStream = Assembly.GetEntryAssembly().GetManifestResourceStream(name);
if ((object)resourceStream != null)
{
byte[] buffer = new byte[resourceStream.Length];
resourceStream.Read(buffer, 0, (int)resourceStream.Length);
resourceStream.Close();
// Loads assembly from binary buffer
resourceAssembly = Assembly.Load(buffer);
// Add assembly to the cache
s_assemblyCache.Add(shortName, resourceAssembly);
}
break;
}
}
}
return resourceAssembly;
}
#endregion
}
}