Wednesday, November 23, 2016

Adding Auto Mapper 5.0.0 Profile Dynamically using Autofac

Introduction.

We would create profile dynamically using reflection and using Autofac we would inject the auto-mapper.

Problem

When we create a lot of profiles. We need to add them in the configuration file as shown below.


Example.

public IMapper ConfigureMapper()
{
   var config = new MapperConfiguration(cfg =>
   {
     cfg.AddProfile<Employee>();
     cfg.AddProfile<Author>();
     cfg.AddProfile<Title>();
                       .
                       .
                       .
                       .
                       .
     cfg.AddProfile<Book>();
                       .
                       .
     //30 more profiles

   });
   return config.CreateMapper();
 }

As the project size grows adding the profiles become tedious and maintainability takes a hit.

Solution 

We would create the profile and them dynamically using reflection code and use Autofac to inject them.

By creating auto-mapper profiles dynamically what do we achieve.

1.Open Closed Principle is not violated.
2.Developers would not add any profiles manually.
3.Code is neatly maintained.

So let’s achieve the same.

Step 1.Create a Common Library in the solution which would be referred by all the other projects in the application.

Step 2.Create a class in Common Library called Auto Mapper Profile which extends a base class “Profile” which is under the auto-mapper dll 

  public class AutoMapperProfile: Profile
  {

  }

3.Now the next step we would create required profiles which extends “AutoMapperProfile” so you would create profiles as given below. 

   public class EmployeeProfile : AutoMapperProfile
    {
       public EmployeeProfile()
       {
           CreateMap<Employee, EmployeeModel>();
       }
    }

Note : If any Profiles that do not extend AutoMapperProfile class then the code would not work.

Step 3.We then need to add the AutoMapperConfiguration class. Where we create a Method that returns IMapper.

public class AutoMapperConfiguration
    {
        public IMapper Configure()
        {
            var profiles =AppDomain.CurrentDomain.GetAssemblies()
              .SelectMany(s => s.GetTypes())
              .Where(a => typeof(AutoMapperProfile).IsAssignableFrom(a));

            // Initialize AutoMapper with each instance of the profiles found.
            var mapperConfiguration = new MapperConfiguration(a =>                                                                  profiles.ForEach(a.AddProfile));

            return mapperConfiguration.CreateMapper();
        }
        
    }


In the above code we have used the reflection to find all the profiles where "AutoMapperProfile" class is extended

If you closely observe in the above code we have used ForEach. We have created an Enumerable extension which create an actionable item for each found profile.

public static class EnumerableExtensions
    {
        public static void ForEach<T>(this IEnumerable<T> enumerable,
                Action<T> action)
        {
            foreach (T item in enumerable) { action(item); }
        }
    }


Step 4: Once we are done with the Creating the Mapper we will return the IMapper to the Autofac object where we create instance for the mapper.

            //Creating an Instance for the Mapper
            builder.RegisterInstance(new AutoMapperConfiguration().Configure()).As<IMapper>();

Step 5: After doing the above steps register the Auto-mapper in the Autofac.

            //Creating an Instance for the Mapper
            builder.RegisterInstance(new AutoMapperConfiguration().Configure()).As<IMapper>();

Step 6:To use the Automapper in the Project just Inject the IMapper in the constructor and it works automatically.
public EmployeeManager(IEmployeeLogic employeelogic, IMapper mapper)
        {
            if (employeelogic== null) throw new ArgumentNullException(nameof(employeelogic));
            _employeelogic = employeelogic;

            if (mapper == null) throw new ArgumentNullException(nameof(mapper));
            _mapper = mapper;
        }

     private async Task<EmployeeModel> GetEmployeeModel(Employee employee)
        {
            var employeeInfoModel = await _exampleCode.GetEmployeeRepo(employee);
            return _mapper.Map<EmployeeModel>(employeeInfoModel );
        }


Just follow the above steps and everything would work seemelesly.

Code is available in the below repository.
https://github.com/BatIronMan007/AutoMapperReflection

Tuesday, November 15, 2016

Creating Dynamic Instances Using Custom Attributes with Constructor Values.

During refactoring of the code. I came across Switch Statement and one of my architect suggested me to use Strategy Pattern to refactor the code.

I did understand the Strategy Pattern and implemented the same. I was a little unhappy with the set of new objects that we were creating in the Context Class of Strategy Pattern.

Every time a  new case is added I had to create a class for the newly added type and add the dictionary value in the Context  class code.

Something struck to my mind and I thought lets use the Reflection Powered by Custom Attributes.

Although Reflection is a powerful tool. We should use it in places where it is really required. (Its like With great power comes great responsibility 😈)

Lets have a quick look at the problem in hand.

   public enum ePassengerTitle
  {
            Mr,
            Mrs,
            Doctor,
   }


    ePassengerTitle title = ePassengerTitle.Doctor;
    switch (title)
    {
                case ePassengerTitle.Mr:
                    // do something
                    break;
                case ePassengerTitle.Mrs:
                    // do something
                    break;
                case ePassengerTitle.Doctor:
                    // do something
                    break;
                default:
                    break;
    }


In the above code there are 3 case conditions and if the cases keep growing the maintainability of the code takes a hit.

Solution to the problem

1.There are multiple ways this problem could be solved. I am going to show how we use custom attributes powered with reflections.

We create different classes for all the "Case" Statements- A little Smell of Strategy Pattern.

An Interface defined.

 public interface IPassengerTitleStrategy
  {
        void DoSomthing(string title);
  }

  [AutoResolve("Mr")]
    public class MrPassengerTitleStrategy : IPassengerTitleStrategy
    {
        public void DoSomthing(string title)
        {
            Console.WriteLine("The Title is" + title);
        }
    }


    [AutoResolve("Mrs")]
    public class MrsPassengerTitleStrategy : IPassengerTitleStrategy
    {
        public void DoSomthing(string title)
        {
            Console.WriteLine("The Title is" + title);
        }
    }

    [AutoResolve("Doctor")]
    public class DoctorPassengerTitleStrategy : IPassengerTitleStrategy
    {
        public void DoSomthing(string title)
        {
            Console.WriteLine("The Title is" + title);
        }
    }

If you closely Observe on each classes we have a Custom Attribute. That Attribute is the Key to the Solution.

Lets Define it now.

 public class AutoResolveAttribute : Attribute
 {
        public AutoResolveAttribute(string name)
        {
            
        }
 }

It has a constructor. Its an important aspect.

Next we need to write Reflection logic which will find you all the classes where the attribute is decorated.

 public static IEnumerable<Type> GetTypesWith<TAttribute>(bool inherit) where TAttribute : System.Attribute
  {
            return from a in AppDomain.CurrentDomain.GetAssemblies()
                   from t in a.GetTypes()
                   where t.IsDefined(typeof(TAttribute), inherit)
                   select t;
   }

So what does the above method do. It searches through all the assemblies in the AppDomain and finds those classes that are decorated with AutoResolve attribute. It is a generic method so you can pass any Attribute of your choice.

Once we get all the classes we need to loop through those classes to find out which class has been decorated with the string value that we are looking for.

   private static string GetAttributeName(string value)
        {
            var getAttribute = GetTypesWith<AutoResolveAttribute>(true);
            foreach (var iAttributeValue in getAttribute)
            {
                var attributeValue = iAttributeValue.CustomAttributes.Select(x =>       x.ConstructorArguments[0].Value).First();
                if (attributeValue.ToString().Contains(value))
                    return iAttributeValue.FullName;
            }
            return string.Empty;
        }


So the above method takes the string as parameter and return the FullName of the assembly.

Once we get the full name of the assembly we now need to get an instance. So we use below code for creating an instance.

   public static object GetInstance(string strFullyQualifiedName)
        {
            Type type = Type.GetType(strFullyQualifiedName);
            if (type != null)
                return Activator.CreateInstance(type);
            return null;
        }

So finally what do we do now.

We use the code. That is so obvious.

  ePassengerTitle title = ePassengerTitle.Doctor;

 var typeCode = GetAttributeName(title.ToString());
 var getInstance = GetInstance(typeCode) as IPassengerTitleStrategy;
 getInstance?.DoSomthing(title.ToString());

 So we get an instance of the specific switch value and you use it ☺☺

Finally what did achieve by doing so.

Pros

1. Eradicated the need to write switch case.
2. Wrote more cleaner more maintainable and scalable code.
3. Code that adheres to  SOLID principles

Con

1.Reflection Code - A powerful tool need to use with care.

Happy Coding 😈😈😈





Log History in Visual Studio Code

It was challenging to find out the log history of what was checked in and who checked in File.

Below is the Extension and Command which we could use for Checking the history and files.

Steps 1. Install the Git History Extension from the market place.

 

Steps 2. Use Ctrl + P and type History and select the 3rd item.



And then you see the History as Shown below.


This gives developers a clear view of the log history.

Happy Coding 😈😈😈