Dependency Injection for Dynamics 365

I have recently come across an article regarding implementing dependency injection for Dynamics 365. It is a great idea because although there are good IoC frameworks out there, like Ninject, debugging a merged plugin library can be a real pain. However, unfortunately, their code sample doesn’t work. So I would like to share my code fixes here.

    public class IocContainer
    {
        private readonly Dictionary<Type, Func<object>> _registrations =
            new Dictionary<Type, Func<object>>();

        public void Register<TService, TImplementation>()
            where TImplementation : TService
        {
            this._registrations.Add(typeof(TService),
                () => this.GetInstance<TImplementation>());
        }

        public void Register<TService>(Func<TService> instanceCreator)
        {
            if (this._registrations.Where(w => w.Key.Equals(typeof(TService))).FirstOrDefault().Key == null)
            {
                this._registrations.Add(typeof(TService), () => instanceCreator());
            }
        }

        public void RegisterSingle<TService>(TService instance)
        {
            if (this._registrations.Where(w => w.Key.Equals(typeof(TService))).FirstOrDefault().Key == null)
            {
                this._registrations.Add(typeof(TService), () => instance);
            }

        }

        public void RegisterSingle<TService>(Func<TService> instanceCreator)
        {
            Lazy<TService> lazy = new Lazy<TService>(instanceCreator);
            this.Register<TService>(() => lazy.Value);
        }

        public TService GetInstance<TService>()
        {
            return (TService)this.GetInstance(typeof(TService));
        }

        public object GetInstance(Type serviceType)
        {
            Func<object> creator;
            if (this._registrations.TryGetValue(serviceType, out creator) == false)
            {
                if (serviceType.IsAbstract == true)
                {
                    throw new InvalidOperationException(
                    "No registration for " + serviceType);
                }
                else
                {
                    var ctor = serviceType.GetConstructor(Type.EmptyTypes);
                    return ctor.Invoke(null);
                }
            }

            return creator.Invoke();
        }
    }

Below is a unit test.

    [TestClass]
    public class When_IocContainer_GetInstance
    {
        [TestMethod]
        public void Given_Depth1Parameters0_Then_ReturnInstance()
        {
            // Arrange
            IocContainer container = new IocContainer();

            container.Register<IWhoAmIService, WhoAmIService>();

            // Action
            var service = container.GetInstance<IWhoAmIService>();

            // Assert
            Assert.IsNotNull(service);
        }
    }

    public interface IWhoAmIService
    {
    }

    public class WhoAmIService : IWhoAmIService
    {
        public WhoAmIService()
        {

        }
    }

Limitations / Future Improvements

  • The container cannot resolve constructors with parameters.
  • The container cannot recursively resolve all dependency classes.

Lesson Learnt

Activator.CreateInstance penalizes performance a lot. The Linq expression alternative is my favorite at the moment.

Change Log

I see my blog posts as living articles so I will log the changes here.

26/Mar/2017 – Version one. The blog post was created.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s