My current project with assemblies for the domain model, MVC web application, and unit tests. How can I set up the AutoMapper configuration so that all assemblies reference the same configuration?
I would guess that I could put items in Global.asax for the web app, but how can I use that in the unit tests? Also, if the config is in Global.asax, will the domain model pick up the map?
Many thanks,
KevDog.
AutoMapper is used whenever there are many data properties for objects, and we need to map them between the object of source class to the object of destination class, Along with the knowledge of data structure and algorithms, a developer is required to have excellent development skills as well.
The AutoMapper in C# is a mapper between two objects. That is AutoMapper is an object-object mapper. It maps the properties of two different objects by transforming the input object of one type to the output object of another type.
What is AutoMapper? AutoMapper is a simple library that helps us to transform one object type into another. It is a convention-based object-to-object mapper that requires very little configuration. The object-to-object mapping works by transforming an input object of one type into an output object of a different type.
automapper Profiles Basic Profile Profiles permit the programmer to organize maps into classes, enhancing code readability and maintainability. Any number of profiles can be created, and added to one or more configurations as needed. Profiles can be used with both the static and instance-based APIs.
What we do is create a static class, something like BootStrapper, and put the initialization code in a static method in there. We're doing profiles, so you don't see much in there. Global.asax will call that at startup, domain will use it (since the configuration is singleton), and unit tests that need it call the BootStrapper.Configure() in their setup.
One final thing we do is keep a flag around on the bootstrapper, and set it to true when we configure. That way, configuration only executes once per AppDomain. That means once at startup of the global.asax (Application_Start), and once when we run unit tests.
HTH
I also use a bootstrapper to handle this sort of startup task thing. Actually, I use a chain of bootstrappers because I am crazy like that. Automapper-wise, we found it was alot cleaner to make some AutoMappingBuddy classes and decorate them with an attribute. We then wire up the mappers via some reflection calls (not cheap, but they only fire once at the get go). This solution was discovered after we got sick of finding an AutoMapper issue in line 841 of a 1200+ line file.
I thought about posting the code, but I can't really call it that purdy. Anyhow, here goes:
First, a simple interface for the AutoMappingBuddies:
public interface IAutoMappingBuddy
{
void CreateMaps();
}
Second, a little attribute to provide some glue:
public class AutoMappingBuddyAttribute : Attribute
{
public Type MappingBuddy { get; private set; }
public AutoMappingBuddyAttribute(Type mappingBuddyType)
{
if (mappingBuddyType == null) throw new ArgumentNullException("mappingBuddyType");
MappingBuddy = mappingBuddyType;
}
public IAutoMappingBuddy CreateBuddy()
{
ConstructorInfo ci = MappingBuddy.GetConstructor(new Type[0]);
if (ci == null)
{
throw new ArgumentOutOfRangeException("mappingBuddyType", string.Format("{0} does not have a parameterless constructor."));
}
object obj = ci.Invoke(new object[0]);
return obj as IAutoMappingBuddy;
}
}
Third, the AutoMappingEngine. It's where the magic happens:
public static class AutoMappingEngine
{
public static void CreateMappings(Assembly a)
{
Dictionary<Type, IAutoMappingBuddy> mappingDictionary = GetMappingDictionary(a);
foreach (Type t in a.GetTypes())
{
var amba =
t.GetCustomAttributes(typeof (AutoMappingBuddyAttribute), true).OfType<AutoMappingBuddyAttribute>().
FirstOrDefault();
if (amba!= null && !mappingDictionary.ContainsKey(amba.MappingBuddy))
{
mappingDictionary.Add(amba.MappingBuddy, amba.CreateBuddy());
}
}
foreach (IAutoMappingBuddy mappingBuddy in mappingDictionary.Values)
{
mappingBuddy.CreateMaps();
}
}
private static Dictionary<Type, IAutoMappingBuddy> GetMappingDictionary(Assembly a)
{
if (!assemblyMappings.ContainsKey(a))
{
assemblyMappings.Add(a, new Dictionary<Type, IAutoMappingBuddy>());
}
return assemblyMappings[a];
}
private static Dictionary<Assembly, Dictionary<Type, IAutoMappingBuddy>> assemblyMappings = new Dictionary<Assembly, Dictionary<Type, IAutoMappingBuddy>>();
}
Kinda slapped together in an hour or so, there are probably more elegant ways to get there.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With