2

We have customers that often have varying requests. Currently, we do things such as if customer_code = ? then ... and do something different just for that customer.

I want to employ something similar to how Wordpress/Magento works where you can subscribe to events, receive the data, process it how you want and then return control back to the application.

I want to store this customer specific functionality inside of an assembly specific to that customer. Note, I don't want to completely override the method, just points within the method to do things (in most instances anyway).

Examples are: - Before order placed - After order placed - Before allocation - After allocation - After status change

asked Jan 20, 2017 at 7:47
1

2 Answers 2

2

There are many ways of doing this in C#. Here are a couple of them:

C# events are extensively used by Win Forms and Web Forms. These feel very much like interrupt handlers, but in reality are just delegates (function pointers).

// Declaration
public event EventHandler BeforeOrderPlaced;
public event EventHandler AfterOrderPlaced;
// Raising events
public void ProcessOrder()
{
 if (BeforeOrderPlaced != null)
 BeforeOrderPlaced(this, new EventArgs());
 PlaceOrder();
 if (AfterOrderPlaced != null)
 AfterOrderPlaced(this, new EventArgs());
}
// Subscribe to events
BeforeOrderPlaced += MyHandler;
private void MyHandler(object sender, EventArgs e)
{
 // do something before the order is placed
}

C# virtual methods is the object-oriented approach.

public class OrderSystem
{
 // Defaults - do nothing
 public virtual void BeforeOrderPlaced() {}
 public virtual void AfterOrderPlaced() {}
 public void ProcessOrder()
 {
 BeforeOrderPlaced();
 PlaceOrder();
 AfterOrderPlaced();
 }
}
// Override the defaults to insert code before/after placing the order.
public class MyOrderSystem : OrderSystem
{
 public override void BeforeOrderPlaced()
 {
 // do something before the order is placed
 } 
}
answered Jan 20, 2017 at 14:26
2

What you are talking about is known as multitenancy.

Here's one way to do it:

  1. Implement basic functionality in non-sealed classes with key methods defined as virtual. Let's imagine for this example that all of your business logic is in a class called BaseBusinessLogic and there is a method called DoSomething().

  2. For customer-specific functionality, write classes that inherit from the basic classes, overriding virtual methods as needed. If Kodak is one of your customers, maybe the class might be defined as class KodakBusinessLogic : BaseBusinessLogic.

  3. Create a database table which maps tenants (perhaps identified by customer_code) onto DLLs and classes. There would be 3 columns:

    customer_code - Whatever datatype you use

    custom_assembly - The name of the DLL, e.g. KodakBusinessLibrary.dll

    class_name - The name of the derived class that contains the customer-specific logic (e.g. KodakBusinessLogic)

  4. When you need to run functionality that may be customer-specific, call a stored procedure to obtain custom_assembly and class_name for that customer_code.

Then you can instantiate the derived class like this:

var asm = Assembly.LoadFile(custom_assembly);
var type = asm.GetType(class_name);
var o = Activator.CreateInstance(type) as BaseBusinessLogic;
if (o == null) throw new Exception("Couldn't load the custom logic.");

And run the customer-specific logic like this:

o.DoSomething();

Even though you have a reference to a BaseBusinessLogic, in reality that pointer is pointing at a KodakBusinessLogic, and calling DoSomething will execute the overridden method that contains the logic for Kodak.

Now, if you don't want to override the method itself, you can define things like this:

class BaseBusinessLogic
{
 public void DoSomething() //notice it's not virtual
 {
 this.OnBeforeProcessing();
 //Execute basic logic here
 this.OnAfterProcessing();
 }
 abstract void OnBeforeProcessing();
 abstract void OnAfterProcessing();
}

Then in your derived class, you just need to override OnBeforeProcessing and OnAfterProcessing.

answered Jan 20, 2017 at 23:37

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.