Latheesan
Latheesan

Reputation: 24116

Create a class from string and execute a method on it

I have two separate/distinct implementation of "Product" sync. They ought to be ran based on sync "Direction" setting.

So, the classes are stored like this on my project:

enter image description here

Both classes identical constructor and a common public "Run" method - which initiates the sync process.

Currently, I am creating an instance of either of these class and executing the "Run" method like this:

private void RunProductSync()
{
    if (_organisation.Data.Settings.Sync.Direction == "IN")
    {
        // Sync IN
        (new Sync.IN.Product(
            _icApi, 
            _icLogger)).Run();
    }
    else if (_organisation.Data.Settings.Sync.Direction == "OUT")
    {
        // Sync OUT
        (new Sync.OUT.Product(
            _icApi,
            _icLogger)).Run();
    }
}

This approach works, but I want to implement a dynamic class instantiation with method invocation.

One approach I tried uses the Activator.CreateInstance feature of .NET, which looks like this:

var sync = Activator.CreateInstance(
    Type.GetType(
        string.Format("Sync.{0}.Product",
            _organisation.Data.Settings.Sync.Direction)));

However, to be able to execute the Run method on this object, I still have to do this:

if (_organisation.Data.Settings.Sync.Direction == "IN") {
    (sync AS Sync.IN.Product).Run();
} else if (_organisation.Data.Settings.Sync.Direction == "OUT") {
    (sync AS Sync.OUT.Product).Run();
}

This is still not any better than what I started with. Is there a better way to do this?


UPDATE

Thanks to @theo - I have the following working great for me:

ISync.cs

interface ISync
{
    void Run();
}

Sync/IN/Product.cs & Sync/OUT/Product.cs

public class Product : ISync
{
    public Product(Api _icApi, Logger _icLogger)
    { ... }

    public void Run()
    { ... }
}

Class is dynamically instantiated & method executed like this:

((ISync)Activator.CreateInstance(
    Type.GetType(
        string.Format("Sync.{0}.Product",
            _organisation.Data.Settings.Sync.Direction)),
    _icApi,
    _icLogger).Run(); 

Upvotes: 1

Views: 117

Answers (1)

Theo
Theo

Reputation: 885

Try adding an IProduct interface to both classes:

public interface IProduct
{
    void Run();
}

then you can do this:

var sync = (IProduct)Activator.CreateInstance(
    Type.GetType(
        string.Format("Sync.{0}.Product",
            _organisation.Data.Settings.Sync.Direction)));

sync.Run();

Upvotes: 1

Related Questions