|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
#nullable disable
namespace Microsoft.Build.Tasks.Deployment.ManifestUtilities
{
/// <summary>
/// Provides a collection for manifest assembly references.
/// </summary>
[ComVisible(false)]
public sealed class AssemblyReferenceCollection : IEnumerable
{
private readonly List<AssemblyReference> _list = new List<AssemblyReference>();
internal AssemblyReferenceCollection(AssemblyReference[] array)
{
if (array == null)
{
return;
}
_list.AddRange(array);
}
/// <summary>
/// Gets the element at the specified index.
/// </summary>
/// <param name="index">The zero-based index of the entry to get.</param>
/// <returns>The assembly reference instance.</returns>
public AssemblyReference this[int index] => _list[index];
/// <summary>
/// Adds the specified assembly reference to the collection.
/// </summary>
/// <param name="path">The specified assembly reference to add.</param>
/// <returns>The added assembly reference instance.</returns>
public AssemblyReference Add(string path)
{
return Add(new AssemblyReference(path));
}
/// <summary>
/// Adds the specified assembly reference to the collection.
/// </summary>
/// <param name="assembly">The specified assembly reference to add.</param>
/// <returns>The added assembly reference instance.</returns>
public AssemblyReference Add(AssemblyReference assembly)
{
_list.Add(assembly);
return assembly;
}
/// <summary>
/// Removes all objects from the collection.
/// </summary>
public void Clear()
{
_list.Clear();
}
/// <summary>
/// Gets the number of objects contained in the collection.
/// </summary>
public int Count => _list.Count;
/// <summary>
/// Finds an assembly reference in the collection by simple name.
/// </summary>
/// <param name="name">The specified assembly simple name.</param>
/// <returns>The found assembly reference.</returns>
public AssemblyReference Find(string name)
{
if (String.IsNullOrEmpty(name))
{
return null;
}
foreach (AssemblyReference a in _list)
{
if (a.AssemblyIdentity != null && String.Equals(
name,
a.AssemblyIdentity.Name,
StringComparison.OrdinalIgnoreCase))
{
return a;
}
}
return null;
}
/// <summary>
/// Finds an assembly reference in the collection by the specified assembly identity.
/// </summary>
/// <param name="identity">The specified assembly identity.</param>
/// <returns>The found assembly reference.</returns>
public AssemblyReference Find(AssemblyIdentity identity)
{
if (identity == null)
{
return null;
}
foreach (AssemblyReference a in _list)
{
AssemblyIdentity listItemIdentity = a.AssemblyIdentity;
// if the item in our list doesn't have an identity but is a managed assembly,
// we calculate it by reading the file from disk to find its identity.
//
// note that this is here specifically to deal with the scenario when we are being
// asked to find a reference to one of our sentinel assemblies which are known to
// be managed assemblies. doing this ensures that our sentinel assemblies do not
// show up twice in the manifest.
//
// we are assuming the incoming identity for the sentinel assembly really is the
// sentinel assembly that MS owns and emits in manifests for ClickOnce application
// prereq verification for .Net 2.0, 3.0 and 3.5 frameworks. otherwise, we expect
// the incoming identity to fail the comparison (because something like the
// public key token won't match if there is a user-owned reference to something
// that has the same name as a sentinel assembly).
//
// note that we only read the file from disk if the incoming identity's name matches
// the file-name of the item in the list to avoid unnecessarily loading every
// reference in the list of references
//
if (listItemIdentity == null &&
identity.Name != null &&
a.SourcePath != null &&
a.ReferenceType == AssemblyReferenceType.ManagedAssembly &&
String.Equals(identity.Name, System.IO.Path.GetFileNameWithoutExtension(a.SourcePath), StringComparison.OrdinalIgnoreCase))
{
listItemIdentity = AssemblyIdentity.FromManagedAssembly(a.SourcePath);
}
if (AssemblyIdentity.IsEqual(listItemIdentity, identity))
{
return a;
}
}
return null;
}
/// <summary>
/// Finds an assembly reference in the collection by the specified target path.
/// </summary>
/// <param name="targetPath">The specified target path.</param>
/// <returns>The found assembly reference.</returns>
public AssemblyReference FindTargetPath(string targetPath)
{
if (String.IsNullOrEmpty(targetPath))
{
return null;
}
foreach (AssemblyReference a in _list)
{
if (String.Equals(targetPath, a.TargetPath, StringComparison.OrdinalIgnoreCase))
{
return a;
}
}
return null;
}
/// <summary>
/// Returns an enumerator that can iterate through the collection.
/// </summary>
/// <returns>The enumerator.</returns>
public IEnumerator GetEnumerator()
{
return _list.GetEnumerator();
}
/// <summary>
/// Removes the specified assembly reference from the collection.
/// </summary>
/// <param name="assemblyReference">The specified assembly reference to remove.</param>
public void Remove(AssemblyReference assemblyReference)
{
_list.Remove(assemblyReference);
}
internal AssemblyReference[] ToArray()
{
return _list.ToArray();
}
}
}
|