tools/AutoMapper/AutoMapperConfigurationException.cs (107 lines of code) (raw):
using System;
using System.Linq;
using System.Text;
namespace AutoMapper
{
public class AutoMapperConfigurationException : Exception
{
public TypeMapConfigErrors[] Errors { get; }
public TypePair? Types { get; }
public PropertyMap PropertyMap { get; set; }
public class TypeMapConfigErrors
{
public TypeMap TypeMap { get; }
public string[] UnmappedPropertyNames { get; }
public bool CanConstruct { get; }
public TypeMapConfigErrors(TypeMap typeMap, string[] unmappedPropertyNames, bool canConstruct)
{
TypeMap = typeMap;
UnmappedPropertyNames = unmappedPropertyNames;
CanConstruct = canConstruct;
}
}
public AutoMapperConfigurationException(string message)
: base(message)
{
}
protected AutoMapperConfigurationException(string message, Exception inner)
: base(message, inner)
{
}
public AutoMapperConfigurationException(TypeMapConfigErrors[] errors) => Errors = errors;
public AutoMapperConfigurationException(TypePair types) => Types = types;
public override string Message
{
get
{
if (Types != null)
{
var message =
string.Format(
"The following property on {0} cannot be mapped: \n\t{2} \nAdd a custom mapping expression, ignore, add a custom resolver, or modify the destination type {1}.",
Types?.DestinationType.FullName, Types?.DestinationType.FullName,
PropertyMap?.DestinationProperty.Name);
message += "\nContext:";
Exception exToUse = this;
while (exToUse != null)
{
if (exToUse is AutoMapperConfigurationException configExc)
{
message += configExc.PropertyMap == null
? $"\n\tMapping from type {configExc.Types?.SourceType.FullName} to {configExc.Types?.DestinationType.FullName}"
: $"\n\tMapping to property {configExc.PropertyMap.DestinationProperty.Name} from {configExc.Types?.SourceType.FullName} to {configExc.Types?.DestinationType.FullName}";
}
exToUse = exToUse.InnerException;
}
return message + "\n" + base.Message;
}
if (Errors != null)
{
var message =
new StringBuilder(
"\nUnmapped members were found. Review the types and members below.\nAdd a custom mapping expression, ignore, add a custom resolver, or modify the source/destination type\nFor no matching constructor, add a no-arg ctor, add optional arguments, or map all of the constructor parameters\n");
foreach (var error in Errors)
{
var len = error.TypeMap.SourceType.FullName.Length +
error.TypeMap.DestinationType.FullName.Length + 5;
message.AppendLine(new string('=', len));
message.AppendLine(error.TypeMap.SourceType.Name + " -> " + error.TypeMap.DestinationType.Name +
" (" +
error.TypeMap.ConfiguredMemberList + " member list)");
message.AppendLine(error.TypeMap.SourceType.FullName + " -> " +
error.TypeMap.DestinationType.FullName + " (" +
error.TypeMap.ConfiguredMemberList + " member list)");
message.AppendLine();
if (error.UnmappedPropertyNames.Any())
{
message.AppendLine("Unmapped properties:");
foreach (var name in error.UnmappedPropertyNames)
{
message.AppendLine(name);
}
}
if (!error.CanConstruct)
{
message.AppendLine("No available constructor.");
}
}
return message.ToString();
}
return base.Message;
}
}
public override string StackTrace
{
get
{
if (Errors != null)
return string.Join(Environment.NewLine,
base.StackTrace
.Split(new[] {Environment.NewLine}, StringSplitOptions.None)
.Where(str => !str.TrimStart().StartsWith("at AutoMapper."))
.ToArray());
return base.StackTrace;
}
}
}
}