Dear Sitecorians, I hope you are doing good.
Today’s post will be about how to inject(and resolve) “generic” configurations to your Sitecore solution. I got inspired by .Net Core, why not try to implement something similar in an Asp.Net Framework solution.
Thank’s to the great post from Brian – Sitecore Advanced Configuration in .config files, I knew how to proceed 🙂
The idea is to have a sitecore config patch, something like this:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"> <sitecore> <MyServiceConfiguration type="MyApp.Feature.SomeFeature.Models.MyServiceConfiguration, MyApp.Feature.SomeFeature"> <SomeIntProperty desc="SomeIntProperty">5</SomeIntProperty> <SomeStringProperty desc="SomeStringProperty">bla bla bla</SomeStringProperty> </SomeConfiguration> </sitecore> </configuration>
Then in my class, I would like to resolve the configuration like this:
public class MyService: IMyService { private readonly IConfigurationResolver<MyServiceConfiguration> _configurationResolver; public MyService(IConfigurationResolver<MyServiceConfiguration> configurationResolver) { _configurationResolver = configurationResolver; } private int MyIntProperty => _configurationResolver.Configuration.SomeIntProperty; private string MyStringProperty => _configurationResolver.Configuration.SomeStringProperty; }
So how do we do this?
Let’s start by creating the “resolving” part. I want it to be generic, which means it should be easy to add “new” configurations (in my Feature/Foundation layers).
We will create a “resolver”, it should reside in the Foundation layer. The resolver will “resolve” 🙂 whatever POCO class we add. The class should, of course, match its properties with the configuration. The mapping/resolving job is done in factory.CreateObject:
namespace MyApp.Foundation.Configurations.Infrastructure { using System.Xml; using Sitecore.Abstractions; public class ConfigurationResolver<T> : IConfigurationResolver<T> where T : class { public T Configuration { get; } public ConfigurationResolver(BaseFactory factory) { XmlNode xmlNode = factory.GetConfigNode(typeof(T).Name); Configuration = factory.CreateObject<T>(xmlNode); } } } namespace MyApp.Foundation.Configurations.Infrastructure { public interface IConfigurationResolver<out T> { T Configuration { get; } } }
Here is the POCO class.
namespace MyApp.Feature.SomeFeature.Models { public class MyServiceConfiguration { public int SomeIntProperty { get; set; } public string SomeStringProperty{ get; set; } } }
And the matching configuration(patch):
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"> <sitecore> <MyServiceConfiguration type="MyApp.Feature.SomeFeature.Models.MyServiceConfiguration, MyApp.Feature.SomeFeature"> <SomeIntProperty desc="SomeIntProperty">5</SomeIntProperty> <SomeStringProperty desc="SomeStringProperty">bla bla bla</SomeStringProperty> </SomeConfiguration> </sitecore> </configuration>
The last and very important part is the implementation of the ConfigurationResolver. We will do this in the ServicesConfigurator class. Every “layer project” should have a ServicesConfigurator, we all love dependency injection 😉
namespace MyApp.Feature.SomeFeature. { using Microsoft.Extensions.DependencyInjection; using Sitecore.DependencyInjection; using MyApp.Foundation.Configurations.Infrastructure; using MyApp.Feature.SomeFeature.Models; public class ServicesConfigurator : IServicesConfigurator { public void Configure(IServiceCollection serviceCollection) { serviceCollection.AddScoped<IConfigurationResolver<MyServiceConfiguration>,ConfigurationResolver<MyServiceConfiguration>>(); } } }
Notice how we set the MyServiceConfiguration to the ConfigurationResolver.
UPDATE
Mike Reynolds has a better approach.
So I feel your resolver object is superfluous when you can inject the POCO instance hydrated from config directly into your service classes.
I’ve done this recently here using a custom attribute where there is boilerplate code in extension methods on IServiceCollection to hydrate these, and register in the IoC container: https://sitecorejunkie.com/2020/05/16/magically-register-sitecore-configuration-objects-in-the-sitecore-ioc-container-using-a-custom-attribute/
I’ve also done this another way without a custom attribute but in the configurators using a method group: https://sitecorejunkie.com/2018/05/28/service-locate-or-create-objects-defined-in-a-fully-qualified-type-name-field-in-sitecore/
That’s all for now folks 🙂
So I feel your resolver object is superfluous when you can inject the POCO instance hydrated from config directly into your service classes.
I’ve done this recently here using a custom attribute where there is boilerplate code in extension methods on IServiceCollection to hydrate these, and register in the IoC container: https://sitecorejunkie.com/2020/05/16/magically-register-sitecore-configuration-objects-in-the-sitecore-ioc-container-using-a-custom-attribute/
I’ve also done this another way without a custom attribute but in the configurators using a method group: https://sitecorejunkie.com/2018/05/28/service-locate-or-create-objects-defined-in-a-fully-qualified-type-name-field-in-sitecore/
LikeLiked by 1 person
Thank you for reading my post and thank you for pointing out there is a better approach. I will update my post, with your comments
LikeLike