0

I am building a middleware integration that will pull orders from various 3rd party API's and push those orders into our system, as well as synchronize stock and send off shipments. I want to build this in such a way that I can add various retailers later on without having to modify the Core project.

I've built this into a few projects:

  • Common (just common things such as WebClient, Serialization, IO etc)
  • ERP (this is the ERP that we will be pushing this data into and this has all the models and services to push orders etc)
  • Core (this will connect to a database to get a list of the various integrations that have been setup, load the providers DLL and then pull the orders etc)
  • Providers.Retailer1 (these have a dependancy on the ERP project as it will return data such as orders in the models from the ERP)
  • Providers.Retailer2
  • Providers.Retailer3

Currently, my Core project has a project reference on the Providers. I want to get to a point whereby the Core doesn't have a hard reference to these providers - perhaps they are loaded dynamically at runtime by checking whether the class implements an interface. So, in theory, if we want to integrate with a new retailer, we would simply build out the implementation of getting orders/syncing stock etc. Does this sound like a sound approach? I was thinking of looking into MEF for this but not sure yet how that would look.

My problem is, is that Retailer1 for example needs certain configurations and services such as ApiKey, Username, Password etc, where as Retailer2 might require different configuration data. Currently, The Core project is what will retrieve these details from the database. What is the best way to pass these to the Providers? Should I create a Configuration object that is basically a key/value pair of the configuration and program the interface to accept a Configuration object? And store these values in a key/value pair in a database table instead of columns as they currently are?

Currently I create the dependencies inside the Core project however this means the Core project is tightly coupled with Retailer1 for example:

         TheIconic.Services.IApiService iconicApiService = new TheIconic.Services.TheIconicApiService(
            DependencyContainerProvider.Current.Container.Resolve<IWebClient>(),
            instance.IntegrationPartner.ApiUrl,
            instance.IntegrationPartner.ApiKey,
            instance.IntegrationPartner.Username,
            instance.IntegrationPartner.BasicAuthUsername,
            instance.IntegrationPartner.BasicAuthPassword
        );
  • If your ERP system is supposed to be agnostic to each provider, then added provider-specific configuration data sounds like you're allowing your ERP database to become polluted by all kinds of data which the ERP system seemingly doesn't need to know about. Have you considered putting the DLL-specific configuration into app.config using ConfigurationManager instead? ( stackoverflow.com/questions/19232695/… ) – Ben Cottrell May 27 '17 at 6:52
  • I don't want to store the configuration in files as I have a separate database to the erp the the "core" project talks to. It has a list of all the different partners, the class that implements their functions as well as any API configuration for that partner. – Lock May 27 '17 at 8:02
  • The Core is coupled to the Retailers once their onfigurations are part of the data model. Aren't they? What's the benefit of storing the configurations in db? Do they change often? – Laiv May 28 '17 at 21:00
  • The benefit of storing it in the DB is that my users can setup these integrations once the programming team has created the provider specific class for this retailer. We will have a front end where a user can "create a new integration" whereby they would put all the settings in (api key, username etc) and this is the configuration that I want to pass to the Retailer class. – Lock May 28 '17 at 22:17
  • Currently, my Core project has a project reference on the Providers. I want to get to a point whereby the Core doesn't have a hard reference to these providers - perhaps they are loaded dynamically at runtime by checking whether the class implements an interface. So, in theory, if we want to integrate with a new retailer, we would simply build out the implementation of getting orders/syncing stock etc. Does this sound like a sound approach?Looks like you are thinking in a modular architecture design. In that case, centralising all the configurations in the Core won't help you to decouple – Laiv May 29 '17 at 8:44
1

Should I create a Configuration object that is basically a key/value pair of the configuration and program the interface to accept a Configuration object?

If a list of key/value pairs is all you need to configure a provider, then yes, this seems like a sound solution. In fact it is the exact solution used by ODBC data providers (via the connection string, which is a list of key/value pairs stored in a text blob).

If you need something more complicated, you can still use a string but perhaps instead of tag/value pairs it could contain XML or JSON.

  • Great point... I never though of a connection string in that sense. – Lock May 31 '17 at 4:01
0

What is the best way to pass these to the Providers?

Why don't you consider DI injection? Create any number of specific data factories for providers, that are using Core classes to build data inside and then pass those factories into Providers' constructors via Dependency Injection library such as NInject. That way your providers are isolated from the core.

  • So in my core, it is still aware of the different configuration options that are available to each provider? Wouldn't this create a circular reference between the Core and the Providers because the providers need to receive the factory? – Lock May 28 '17 at 22:20
  • @Lock No, core doesn't know that. And factory doesn't either. Factories just prepare data in some format and variety using your core services. Neither factories nor core know where factories are going to be injected with. And you just inject a factory into a provider. – Vladislav Rastrusny May 29 '17 at 6:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.