|
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using Mono.Cecil;
namespace Mono.Linker
{
public class InterfaceImplementor
{
/// <summary>
/// The type that implements <see cref="InterfaceImplementor.InterfaceType"/>.
/// </summary>
public TypeDefinition Implementor { get; }
/// <summary>
/// The .interfaceimpl on <see cref="InterfaceImplementor.Implementor"/>that points to <see cref="InterfaceImplementor.InterfaceType"/>
/// </summary>
public InterfaceImplementation InterfaceImplementation { get; }
/// <summary>
/// The type of the interface that is implemented by <see cref="InterfaceImplementor.Implementor"/>
/// </summary>
public TypeDefinition InterfaceType { get; }
public InterfaceImplementor (TypeDefinition implementor, InterfaceImplementation interfaceImplementation, TypeDefinition interfaceType, IMetadataResolver resolver)
{
Implementor = implementor;
InterfaceImplementation = interfaceImplementation;
InterfaceType = interfaceType;
Debug.Assert(resolver.Resolve (interfaceImplementation.InterfaceType) == interfaceType);
}
public static InterfaceImplementor Create(TypeDefinition implementor, TypeDefinition interfaceType, IMetadataResolver resolver)
{
foreach(InterfaceImplementation iface in implementor.Interfaces) {
if (resolver.Resolve(iface.InterfaceType) == interfaceType) {
return new InterfaceImplementor(implementor, iface, interfaceType, resolver);
}
}
Queue<TypeDefinition> ifacesToCheck = new ();
ifacesToCheck.Enqueue(implementor);
while (ifacesToCheck.Count > 0) {
var currentIface = ifacesToCheck.Dequeue ();
foreach(InterfaceImplementation ifaceImpl in currentIface.Interfaces) {
var iface = resolver.Resolve (ifaceImpl.InterfaceType);
if (iface == interfaceType) {
return new InterfaceImplementor(implementor, ifaceImpl, interfaceType, resolver);
}
ifacesToCheck.Enqueue (iface);
}
}
throw new InvalidOperationException ($"Type '{implementor.FullName}' does not implement interface '{interfaceType.FullName}' directly or through any interfaces");
}
}
}
|