Version 5.4.2.1: Fixed unnecessary assembly table construction (Issue #84).

This commit is contained in:
ClearScript 2015-06-23 14:17:30 -04:00
Родитель bfd06449d9
Коммит 8baf6a9ee6
13 изменённых файлов: 219 добавлений и 131 удалений

Просмотреть файл

@ -83,6 +83,7 @@
<Compile Include="ScriptMethod.cs" />
<Compile Include="ScriptMemberAttribute.cs" />
<Compile Include="ScriptUsageAttribute.cs" />
<Compile Include="Util\AssemblyHelpers.cs" />
<Compile Include="Util\Collateral.cs" />
<Compile Include="Util\COMDispatchHelpers.cs" />
<Compile Include="Util\CoTaskMemBlock.cs" />
@ -123,7 +124,7 @@
</Compile>
<Compile Include="HostTypeCollection.cs" />
<Compile Include="Util\ArrayHelpers.cs" />
<Compile Include="Util\AssemblyHelpers.cs" />
<Compile Include="Util\AssemblyTable.cs" />
<Compile Include="Util\DynamicHelpers.cs" />
<Compile Include="Util\EnumerableHelpers.cs" />
<Compile Include="Util\InvokeHelpers.cs" />

Просмотреть файл

@ -63,5 +63,5 @@
#pragma once
#define CLEARSCRIPT_VERSION_STRING "5.4.2.0"
#define CLEARSCRIPT_VERSION_COMMA_SEPARATED 5,4,2,0
#define CLEARSCRIPT_VERSION_STRING "5.4.2.1"
#define CLEARSCRIPT_VERSION_COMMA_SEPARATED 5,4,2,1

Просмотреть файл

@ -158,7 +158,7 @@ namespace Microsoft.ClearScript
public void AddAssembly(string assemblyName)
{
MiscHelpers.VerifyNonBlankArgument(assemblyName, "assemblyName", "Invalid assembly name");
AddAssembly(Assembly.Load(AssemblyHelpers.GetFullAssemblyName(assemblyName)));
AddAssembly(Assembly.Load(AssemblyTable.GetFullAssemblyName(assemblyName)));
}
/// <summary>
@ -186,7 +186,7 @@ namespace Microsoft.ClearScript
public void AddAssembly(string assemblyName, Predicate<Type> filter)
{
MiscHelpers.VerifyNonBlankArgument(assemblyName, "assemblyName", "Invalid assembly name");
AddAssembly(Assembly.Load(AssemblyHelpers.GetFullAssemblyName(assemblyName)), filter);
AddAssembly(Assembly.Load(AssemblyTable.GetFullAssemblyName(assemblyName)), filter);
}
/// <summary>

Просмотреть файл

@ -75,5 +75,5 @@ using System.Runtime.InteropServices;
[assembly: InternalsVisibleTo("ClearScriptTest")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("5.4.2.0")]
[assembly: AssemblyFileVersion("5.4.2.0")]
[assembly: AssemblyVersion("5.4.2.1")]
[assembly: AssemblyFileVersion("5.4.2.1")]

Просмотреть файл

@ -60,131 +60,16 @@
//
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Binary;
using Microsoft.Win32;
namespace Microsoft.ClearScript.Util
{
internal static class AssemblyHelpers
{
private static ConcurrentDictionary<string, string> table;
static AssemblyHelpers()
{
LoadAssemblyTable();
if (table != null)
{
AppDomain.CurrentDomain.AssemblyLoad += (sender, args) => table.TryAdd(args.LoadedAssembly.GetName().Name, args.LoadedAssembly.FullName);
AppDomain.CurrentDomain.GetAssemblies().ForEach(assembly => table.TryAdd(assembly.GetName().Name, assembly.FullName));
}
}
public static string GetFullAssemblyName(string name)
{
string fullName;
return ((table != null) && table.TryGetValue(name, out fullName)) ? fullName : name;
}
public static T GetAttribute<T>(this Assembly assembly, bool inherit) where T : Attribute
{
return Attribute.GetCustomAttributes(assembly, typeof(T), inherit).SingleOrDefault() as T;
}
private static void LoadAssemblyTable()
{
// ReSharper disable EmptyGeneralCatchClause
string filePath = null;
try
{
var dirPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
if (!string.IsNullOrWhiteSpace(dirPath))
{
dirPath = Path.Combine(dirPath, "Microsoft", "ClearScript", Environment.Is64BitProcess ? "x64" : "x86", GetRuntimeVersionDirectoryName());
Directory.CreateDirectory(dirPath);
filePath = Path.Combine(dirPath, "AssemblyTable.bin");
if (File.Exists(filePath))
{
try
{
using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
var formatter = new BinaryFormatter();
table = (ConcurrentDictionary<string, string>)formatter.Deserialize(stream);
}
}
catch (Exception)
{
}
}
}
}
catch (Exception)
{
}
if (table == null)
{
BuildAssemblyTable();
if ((table != null) && (filePath != null))
{
try
{
using (var stream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
{
var formatter = new BinaryFormatter();
formatter.Serialize(stream, table);
}
}
catch (Exception)
{
}
}
}
// ReSharper restore EmptyGeneralCatchClause
}
private static void BuildAssemblyTable()
{
// ReSharper disable EmptyGeneralCatchClause
try
{
var key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\.NETFramework");
if (key != null)
{
var dirPath = Path.Combine((string)key.GetValue("InstallRoot"), GetRuntimeVersionDirectoryName());
table = new ConcurrentDictionary<string, string>();
foreach (var filePath in Directory.EnumerateFiles(dirPath, "*.dll", SearchOption.AllDirectories))
{
try
{
var assemblyName = Assembly.ReflectionOnlyLoadFrom(filePath).GetName();
table.TryAdd(assemblyName.Name, assemblyName.FullName);
}
catch (Exception)
{
}
}
}
}
catch (Exception)
{
}
// ReSharper restore EmptyGeneralCatchClause
}
private static string GetRuntimeVersionDirectoryName()
{
return MiscHelpers.FormatInvariant("v{0}", Environment.Version.ToString(3));
}
}
}

Просмотреть файл

@ -0,0 +1,184 @@
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Microsoft Public License (MS-PL)
//
// This license governs use of the accompanying software. If you use the
// software, you accept this license. If you do not accept the license, do not
// use the software.
//
// 1. Definitions
//
// The terms "reproduce," "reproduction," "derivative works," and
// "distribution" have the same meaning here as under U.S. copyright law. A
// "contribution" is the original software, or any additions or changes to
// the software. A "contributor" is any person that distributes its
// contribution under this license. "Licensed patents" are a contributor's
// patent claims that read directly on its contribution.
//
// 2. Grant of Rights
//
// (A) Copyright Grant- Subject to the terms of this license, including the
// license conditions and limitations in section 3, each contributor
// grants you a non-exclusive, worldwide, royalty-free copyright license
// to reproduce its contribution, prepare derivative works of its
// contribution, and distribute its contribution or any derivative works
// that you create.
//
// (B) Patent Grant- Subject to the terms of this license, including the
// license conditions and limitations in section 3, each contributor
// grants you a non-exclusive, worldwide, royalty-free license under its
// licensed patents to make, have made, use, sell, offer for sale,
// import, and/or otherwise dispose of its contribution in the software
// or derivative works of the contribution in the software.
//
// 3. Conditions and Limitations
//
// (A) No Trademark License- This license does not grant you rights to use
// any contributors' name, logo, or trademarks.
//
// (B) If you bring a patent claim against any contributor over patents that
// you claim are infringed by the software, your patent license from such
// contributor to the software ends automatically.
//
// (C) If you distribute any portion of the software, you must retain all
// copyright, patent, trademark, and attribution notices that are present
// in the software.
//
// (D) If you distribute any portion of the software in source code form, you
// may do so only under this license by including a complete copy of this
// license with your distribution. If you distribute any portion of the
// software in compiled or object code form, you may only do so under a
// license that complies with this license.
//
// (E) The software is licensed "as-is." You bear the risk of using it. The
// contributors give no express warranties, guarantees or conditions. You
// may have additional consumer rights under your local laws which this
// license cannot change. To the extent permitted under your local laws,
// the contributors exclude the implied warranties of merchantability,
// fitness for a particular purpose and non-infringement.
//
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Binary;
using Microsoft.Win32;
namespace Microsoft.ClearScript.Util
{
internal static class AssemblyTable
{
private static ConcurrentDictionary<string, string> table;
static AssemblyTable()
{
LoadAssemblyTable();
if (table != null)
{
AppDomain.CurrentDomain.AssemblyLoad += (sender, args) => table.TryAdd(args.LoadedAssembly.GetName().Name, args.LoadedAssembly.FullName);
AppDomain.CurrentDomain.GetAssemblies().ForEach(assembly => table.TryAdd(assembly.GetName().Name, assembly.FullName));
}
}
public static string GetFullAssemblyName(string name)
{
string fullName;
return ((table != null) && table.TryGetValue(name, out fullName)) ? fullName : name;
}
private static void LoadAssemblyTable()
{
// ReSharper disable EmptyGeneralCatchClause
string filePath = null;
try
{
var dirPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
if (!string.IsNullOrWhiteSpace(dirPath))
{
dirPath = Path.Combine(dirPath, "Microsoft", "ClearScript", Environment.Is64BitProcess ? "x64" : "x86", GetRuntimeVersionDirectoryName());
Directory.CreateDirectory(dirPath);
filePath = Path.Combine(dirPath, "AssemblyTable.bin");
if (File.Exists(filePath))
{
try
{
using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
var formatter = new BinaryFormatter();
table = (ConcurrentDictionary<string, string>)formatter.Deserialize(stream);
}
}
catch (Exception)
{
}
}
}
}
catch (Exception)
{
}
if (table == null)
{
BuildAssemblyTable();
if ((table != null) && (filePath != null))
{
try
{
using (var stream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
{
var formatter = new BinaryFormatter();
formatter.Serialize(stream, table);
}
}
catch (Exception)
{
}
}
}
// ReSharper restore EmptyGeneralCatchClause
}
private static void BuildAssemblyTable()
{
// ReSharper disable EmptyGeneralCatchClause
try
{
var key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\.NETFramework");
if (key != null)
{
var dirPath = Path.Combine((string)key.GetValue("InstallRoot"), GetRuntimeVersionDirectoryName());
table = new ConcurrentDictionary<string, string>();
foreach (var filePath in Directory.EnumerateFiles(dirPath, "*.dll", SearchOption.AllDirectories))
{
try
{
var assemblyName = Assembly.ReflectionOnlyLoadFrom(filePath).GetName();
table.TryAdd(assemblyName.Name, assemblyName.FullName);
}
catch (Exception)
{
}
}
}
}
catch (Exception)
{
}
// ReSharper restore EmptyGeneralCatchClause
}
private static string GetRuntimeVersionDirectoryName()
{
return MiscHelpers.FormatInvariant("v{0}", Environment.Version.ToString(3));
}
}
}

Просмотреть файл

@ -521,7 +521,7 @@ namespace Microsoft.ClearScript.Util
if (useAssemblyName)
{
fullTypeName += MiscHelpers.FormatInvariant(", {0}", AssemblyHelpers.GetFullAssemblyName(assemblyName));
fullTypeName += MiscHelpers.FormatInvariant(", {0}", AssemblyTable.GetFullAssemblyName(assemblyName));
}
return fullTypeName;

Просмотреть файл

@ -69,5 +69,5 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCopyright("(c) Microsoft Corporation")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("5.4.2.0")]
[assembly: AssemblyFileVersion("5.4.2.0")]
[assembly: AssemblyVersion("5.4.2.1")]
[assembly: AssemblyFileVersion("5.4.2.1")]

Просмотреть файл

@ -69,5 +69,5 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCopyright("(c) Microsoft Corporation")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("5.4.2.0")]
[assembly: AssemblyFileVersion("5.4.2.0")]
[assembly: AssemblyVersion("5.4.2.1")]
[assembly: AssemblyFileVersion("5.4.2.1")]

Просмотреть файл

@ -1208,6 +1208,24 @@ namespace Microsoft.ClearScript.Test
Array.ForEach(engines, tempEngine => tempEngine.Dispose());
}
[TestMethod, TestCategory("BugFix")]
public void BugFix_AssemblyTableClass()
{
Assert.IsTrue(typeof(AssemblyTable).IsStatic());
Assert.IsNotNull(typeof(AssemblyTable).TypeInitializer);
var methods = typeof(AssemblyTable).GetMethods(BindingFlags.Static | BindingFlags.Public);
Assert.AreEqual(1, methods.Length);
Assert.AreEqual("GetFullAssemblyName", methods[0].Name);
}
[TestMethod, TestCategory("BugFix")]
public void BugFix_AssemblyHelpersClass()
{
Assert.IsTrue(typeof(AssemblyHelpers).IsStatic());
Assert.IsNull(typeof(AssemblyHelpers).TypeInitializer);
}
// ReSharper restore InconsistentNaming
#endregion

Просмотреть файл

@ -142,7 +142,7 @@ namespace Microsoft.ClearScript.Test
private static IEnumerable<Type> GetImportableTypes(string[] assemblyNames, Predicate<Type> filter)
{
var assemblies = assemblyNames.Select(assemblyName => Assembly.Load(AssemblyHelpers.GetFullAssemblyName(assemblyName)));
var assemblies = assemblyNames.Select(assemblyName => Assembly.Load(AssemblyTable.GetFullAssemblyName(assemblyName)));
var activeFilter = filter ?? defaultFilter;
return assemblies.SelectMany(assembly => assembly.GetTypes().Where(type => type.IsImportable() && activeFilter(type)));
}

Просмотреть файл

@ -69,5 +69,5 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCopyright("(c) Microsoft Corporation")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("5.4.2.0")]
[assembly: AssemblyFileVersion("5.4.2.0")]
[assembly: AssemblyVersion("5.4.2.1")]
[assembly: AssemblyFileVersion("5.4.2.1")]

Просмотреть файл

@ -1 +1 @@
<# var version = new Version(5, 4, 2, 0); #>
<# var version = new Version(5, 4, 2, 1); #>