Register a Custom Component
When you're extending Ucommerce you often need to register a component whether it is a pipeline task, a payment method service or any other type that is extendable in Ucommerce. You can also append your own components.
To do so you must follow a few basic principles.
Component Basics
When you register a component you do it in XML. You'll need to specify 3 things:
- An Id of your component
- The service that your component exposes - usually an interface, but can also be a class
- The specific type of the implementation of your component - always a class
Also, namespaces and assemblies must be specified. (If you base a component from a redirected assembly, version numbers to the assembly must also be specified).
Last but not least, you need to register your component by placing your config file in Ucommerce/Apps/MyApp
. From there Ucommerce automatically picks up additional components at application startup.
If you wish to disable apps, you can suffix folders or file names with the ".disabled" extension, which causes Ucommerce to ignore the folder (and everything in it) or file.
When registering a component, use the following format:
<component id="PriceService" service="UCommerce.Catalog.IPricingService, UCommerce" type="UCommerce.Catalog.PricingService, UCommerce" />
The above example is a registration of the default component IPricingService. The component is registered with the ID "PriceService", which can be used to get the exact implementation of the service it is registered under, if you need to do so. More about that later.
It's based on the Interface IPricingService, which is an interface
located in the assembly UCommerce
, found in the namespace UCommerce.Catalog
.
The implementation of the service is the class called PricingService
, which is found in the assembly UCommerce
with the namespace UCommerce.Catalog
.
Overriding a Default Component
When you need to override specific services, you must register your overrides using the same Id as the existing component.
For example, to override the PriceService
from before you would copy/paste the registration of the component from Core.config to your own configuration file and change the type of the component to point to your new type:
<component id="PriceService" service="UCommerce.Catalog.IPricingService, UCommerce" type="MyNamespace.MyPriceService, MyDll" />
Notice that the ID is the same as the default registration, but the type now points to MyNamespace.MyPriceService, MyDll
.
This effectively redirects all calls from the default price service to your implementation and can be done for any components Ucommerce ships out of the box.
It happens both for existing usages in Ucommerce and any new usages you add to the system as the following example illustrates.
Constructor Injected Components
Components can be composed using other components. What this means is that you can create highly focused components, which do just one thing and later on "click" them together to solve a task together.
Constructor injection is a way to achieve this without the components knowing that they're operating in an injected environment.
Consider a pipeline task: The task is part of the overall framework of Ucommerce and as such is injected into the pipeline executing it.
The pipeline task might need other components to complete its job; these can be injected just like the pipeline task itself is. You might need access to other components shipped with Ucommerce such as the IPriceService
discussed above or entirely new ones created just for the occasion:
public class MyPipelineTask : IPipelineTask<PurchaseOrder> { private readonly IPricingService _priceService; private readonly IMyNewComponent _myNewComponent; public MyPipelineTask( IPricingService priceService, IMyNewComponent myNewComponent) { // priceService is provided automatically to MyPipelineTask // because it's registered with Ucommerce _priceService = priceService; // Works for entirely new components too _myNewComponent = myNewComponent; } public PipelineExecutionResult Execute(PurchaseOrder subject) { // Do some price calculation return PipelineExecutionResult.Success; } }
As you can see from the example MyPipelineTask
receives both the existing IPricingService
and the completely new component IMyNewComponent
and can use the instances to perform its job.
Registering a folder of configuration files
You have the ability to register a folder of configuration files that will be included when the application starts. To register a folder you can use the following syntax:
<include-folder path="Folder path and folder name" />
The value of "path" is a virtual path, and starts from the file where you're using the include-folder feature. You can navigate up and down the folder path as you wish. Per default, all subfolders and files will recursively be appended as well. You can prevent this behavior by adding an attribute "exclude-subfolders" and setting the value to "true".
Another way of excluding specific folders is by adding ".disabled" to the end of the folder name. This will make Ucommerce ignore that specific folder.
Getting and Using Registered Components
When you need to use any given service in Ucommerce you can resolve them from ObjectFactory
- either by Id for an exact implementation of a service or by service/interface for any given implementation.
You can also get a list of all implementations for a specific service/interface.
Fetching services is possible by using the static methods on ObjectFactory
. To use it, you'll need a reference to UCommerce.Infrastructure.dll
in your solution.
ObjectFactory.Instance .Resolve<T>() .Resolve<T>(id) .ResolveAll<T>() .RegisteredServicesFor<T>()
Quick Note on Pipelines
If you are looking to modify a pipeline component, please refer to the "Configure the Pipeline" section in Create Pipeline Task article.
Performance measurements of components
From version 6.7.3, it is now possible to log performance measurements for any component, without changing the component itself.
Simply add a partial component configuration to your custom configuration, that adds the TimingInterceptor component.
In this example, timing is added to the TaxService.
<configuration> <components> <partial-component id="TaxService"> <interceptors> <interceptor>${TimingInterceptor}</interceptor> </interceptors> </partial-component> </components> </configuration>