diff --git a/FastMoq.Core/Extensions/TestClassExtensions.cs b/FastMoq.Core/Extensions/TestClassExtensions.cs index 0954644..88f695a 100644 --- a/FastMoq.Core/Extensions/TestClassExtensions.cs +++ b/FastMoq.Core/Extensions/TestClassExtensions.cs @@ -4,6 +4,7 @@ using System.Reflection; using System.Runtime; using System.Runtime.CompilerServices; +using System.Text; using Xunit.Abstractions; namespace FastMoq.Extensions @@ -267,9 +268,10 @@ public static string GetMemberName(this T _, Expression /// The mocker. /// Type of the t. + /// The type list. /// Type. /// - public static Type GetTypeFromInterface(this Mocker mocker, Type tType) + public static Type GetTypeFromInterface(this Mocker mocker, Type tType, List? typeList = null) { if (!tType.IsInterface) { @@ -283,8 +285,12 @@ public static Type GetTypeFromInterface(this Mocker mocker, Type tType) return mappedType.InstanceType; } - var types = tType.Assembly.GetTypes().ToList(); + var types = typeList ?? tType.Assembly.GetTypes().ToList(); + return GetTypeFromInterfaceList(mocker, tType, types); + } + private static Type GetTypeFromInterfaceList(Mocker mocker, Type tType, List types) + { // Get interfaces that contain T. var interfaces = types.Where(type => type.IsInterface && type.GetInterfaces().Contains(tType)).ToList(); @@ -298,13 +304,54 @@ public static Type GetTypeFromInterface(this Mocker mocker, Type tType) return possibleTypes.Count switch { > 1 => possibleTypes.Count(x => x.IsPublic) > 1 - ? throw new AmbiguousImplementationException() + ? throw mocker.GetAmbiguousImplementationException(tType, possibleTypes) : possibleTypes.Find(x => x.IsPublic) ?? possibleTypes.FirstOrDefault() ?? tType, 1 => possibleTypes[0], _ => tType, }; } + /// + /// Throws the ambiguous implementation exception. + /// + /// The mocker. + /// The message. + /// System.Runtime.AmbiguousImplementationException. + public static AmbiguousImplementationException GetAmbiguousImplementationException(this Mocker mocker, string message) + { + mocker.exceptionLog.Add(message); + return new AmbiguousImplementationException(message); + } + + /// + /// Gets the ambiguous implementation exception. + /// + /// The mocker. + /// Type of the t. + /// The types. + /// System.Runtime.AmbiguousImplementationException. + public static AmbiguousImplementationException GetAmbiguousImplementationException(this Mocker mocker, Type tType, ICollection? types = null) + { + var builder = new StringBuilder($"Multiple components of type '{tType}' was found."); + + if (types?.Count > 1) + { + builder.AppendLine("\r\nTypes found:"); + + builder.AppendJoin(", ", types.Select(x => x.FullName)); + } + return mocker.GetAmbiguousImplementationException(builder.ToString()); + } + + /// + /// Throws the ambiguous constructor implementation exception. + /// + /// The mocker. + /// Type of the t. + /// System.Runtime.AmbiguousImplementationException. + public static AmbiguousImplementationException GetAmbiguousConstructorImplementationException(this Mocker mocker, Type tType) => + mocker.GetAmbiguousImplementationException($"Multiple parameterized constructors exist of type '{tType}'. Cannot decide which to use."); + /// /// Sets the field value. ///