In my current project, we are still using .NET Framework for several applications. At one point, I needed to use a custom TypeConverter
from AutoMapper during the mapping process. However, I wanted to inject an object into the TypeConverter
using Autofac, and it wasn't immediately clear how to achieve this. While searching the internet, I found plenty of information for .NET (Core), but for .NET Framework, only a few pieces of the puzzle were provided.
After some experimentation, I managed to piece everything together. Below is a comprehensive code sample that demonstrates the solution. You can easily run this in Visual Studio 2022—simply create a new Console Application targeting .NET Framework, paste the sample code, and you're all set to run and learn!
using Autofac; // 7.1.0
using AutoMapper; // 10.0.0
using System; // .NET Framework 4.8
namespace ConsoleApp7
{
// a person-class, which we will map from
public class Person
{
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
}
// another person-class, which we will map to
public class PersonDto
{
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
}
// a simple interface for the object that we want to inject
public interface IStringMaker
{
string Create();
}
// a simple implementation to create a simple string
public class StringMaker : IStringMaker
{
public string Create()
{
return "abc123";
}
}
// A custom AutoMapper Type Converter.
public class MyTypeConverter : ITypeConverter<Person, PersonDto>
{
private readonly IStringMaker _stringMaker;
// The constructor gets injected by an interface
public MyTypeConverter(IStringMaker stringMaker)
{
_stringMaker = stringMaker;
}
public PersonDto Convert(Person source, PersonDto destination, ResolutionContext context)
{
return new PersonDto
{
Name = $"converted {source.Name} {_stringMaker.Create()}", // note that the injected object gets used here
DateOfBirth = source.DateOfBirth
};
}
}
internal class Program
{
static void Main(string[] args)
{
// SETUP starts here
// AutoFac
var builder = new ContainerBuilder();
// register both the object to inject and the type converter
builder.RegisterType<StringMaker>()
.As<IStringMaker>();
builder.RegisterType<MyTypeConverter>();
// register the AutoMapper mappingconfiguration
var mapperConfig = new MapperConfiguration(cfg => cfg.CreateMap<Person, PersonDto>().ConvertUsing<MyTypeConverter>());
builder.Register(c => mapperConfig);
// register the mapper itself
builder.Register(c => {
var context = c.Resolve<IComponentContext>();
var config = context.Resolve<MapperConfiguration>();
return config.CreateMapper(context.Resolve);
}).As<IMapper>();
var container = builder.Build();
// SETUP ends here
// retrieve the mapper from AutoFac
var mapper = container.Resolve<IMapper>();
var person = new Person { Name = "John", DateOfBirth = new DateTime(1990, 12, 6) };
var dto = mapper.Map<Person, PersonDto>(person);
// dto.Name will be "converted John abc123" at this point
Console.ReadLine();
}
}
}