0
\$\begingroup\$

I currently have two (core) classes :

public abstract class BO<TConfig> where TConfig : BOConfigBase
{
    protected TConfig Config { get; set; }
    internal List<BC> _BCs { get; set; }

    public abstract void Init();

    public void Process() => _BCs.ForEach(bc => bc.Process());
}

public class BOOne : BO<BOConfigOne>
{
    public BOOne(BOConfigOne config)
    {
        Config = config;
    }

    public override void Init()
    {
        _BCs = new List<BC>()
        {
            BCA.Init(Config),
            BCB.Init(Config),
            BCC.Init(Config),
            BCOneA.Init(Config)
        };
    }
}

Then the code for my BCs

public abstract class BC
{
    protected BOConfigBase Config { get; set; }
    public abstract void Process();
}

public class BCA : BC
{
    private BCA()
    {
    }

    public static BCA Init(BOConfigBase config)
    {
        BCA ret = new BCA { Config = config };
        return ret;
    }

    public override void Process()
    {
        Config.Counter += 1;
    }
}

To call this, I will do this :

    static void Main()
    {
        {
            var boConfigOne = new BOConfigOne()
            {
                A = "one",
                B = "one",
                C = "one",
                One = "one"
            };
            var testBO = new BOOne(boConfigOne);
            testBO.Init();
            testBO.Process();
            Console.WriteLine(
                $"A = {boConfigOne.A}, B = {boConfigOne.B}, C = {boConfigOne.C}, One = {boConfigOne.One}, Counter = {boConfigOne.Counter}");
        }

        {
            var boConfigTwo = new BOConfigTwo()
            {
                A = "two",
                B = "two",
                C = "two",
                Two = "two"
            };

            var testBOTwo = new BOTwo(boConfigTwo);
            testBOTwo.Init();
            testBOTwo.Process();
            Console.WriteLine(
                $"A = {boConfigTwo.A}, B = {boConfigTwo.B}, C = {boConfigTwo.C}, Two = {boConfigTwo.Two}, Counter = {boConfigTwo.Counter}");
        }
        Console.ReadKey();
    }

BO stands for Business Orchestration, and BC for Business Component. A BC would perform a single function, and a BO would contain several of these re-usable BCs.

I would like to change the BO to be able to Init all the BCs generically, something like Init => BCs.Foreach(bc => bc.Init(Config));. The problem is that my BC's Init's are static, hence I can't put it in an interface, and call it on the interface, nor can I put it in the base abstract method, and override it.

Does anyone have a better solution for me?

\$\endgroup\$
  • \$\begingroup\$ We can help you (better) and review the code when you show us your real implementation. This looks very much like pseudocode or hypothetical one. \$\endgroup\$ – t3chb0t Apr 23 at 8:23
  • \$\begingroup\$ @t3chb0t. This is the current working set of code I have as a POC. If I can get this to work, I will then implement it completely. I'll add the basic call of the methods to show the test implementation of it as well. \$\endgroup\$ – WynDiesel Apr 23 at 8:26
  • 1
    \$\begingroup\$ This is a very good idea. Could you tell us at least what BCA, BO etc stand for so we have some more context? \$\endgroup\$ – t3chb0t Apr 23 at 8:27
  • \$\begingroup\$ @t3chb0t, my apologies. So used to use the terms in my environment, I forgot to add. BC stands for Business Component, BO stands for Business Orchestration. So, a BO would contain several (reusable in other BO) BC's, that would perform a single function, like updating the DB, writing a file, etc. \$\endgroup\$ – WynDiesel Apr 23 at 8:28
1
\$\begingroup\$

To be honest it's hard to follow with such abstract class names and POC. The root of what you are describing is you have a factory method to create one of your classes. Lucky for you it seems all the factory methods have the same method signature. We can make this a bit easier.

Need to store the factory methods in a private field to be used by the Init method. Also adding a "helper" method to make storing the factories easier.

public abstract class BO<TConfig> where TConfig : BOConfigBase
{
    protected TConfig Config { get; set; }
    internal List<BC> _BCs { get; set; }
    private Func<BOConfigBase, BC>[] _factories = new Func<BOConfigBase, BC>[0];

    protected void SetFactories(params Func<BOConfigBase, BC>[] factories)
    {
        _factories = factories;
    }

    public void Init()
    {
        _BCs = _factories.Select(b => b(Config)).ToList();
    }

    public void Process() => _BCs.ForEach(bc => bc.Process());
}

Now BOOne class can call it like

public class BOOne : BO<BOConfigOne>
{
    public BOOne(BOConfigOne config)
    {
        Config = config;
        SetFactories(BCA.Init, BCB.Init, BCC.Init, BCOneA.Init);
    }
}

I'm assuming each BO class would take different BC classes if not then you could constructer inject all the factories.

\$\endgroup\$

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.