Emily Samantha Heiner
Emily Samantha Heiner

Reputation: 121

Best way to access settings from parent class in child class

I have a project where I'm implementing an API that has about 300 methods and I want to separate them out so they're organized by the API category.

I'm trying to lay out my classes so that I have a parent class that has settings, and organize child classes inside of the parent that have access to those settings. I found a horribly convoluted way to do this that probably breaks every rule on the planet. Is there a more standardized way of going about this than what I've come up with?

I want to be able to create an instance of the parent class like:

var foo = new Foo(new FooSettings("Hello"));

and be able to access the functions in the child classes like:

foo.Bar1.WriteTag();
foo.Settings.Tag = "Woot";
foo.Bar2.WriteTag();

with Bar1 and Bar2 having access to the settings I gave when I created the instance of Foo. My current class layout is:

public class Foo
{
    public FooSettings Settings;

    public FooMethods.Bar1 Bar1 { get; }
    public FooMethods.Bar2 Bar2 { get; }

    public Foo(FooSettings settings)
    {
        Settings = settings;
        Bar1 = new FooMethods.Bar1(ref Settings);
        Bar2 = new FooMethods.Bar2(ref Settings);
    }
}

public class FooSettings
{
    public string Tag { get; set; }

    public FooSettings(string tag)
    {
        Tag = tag;
    }
}

public class FooMethods
{
    public class Bar1
    {
        private FooSettings Settings { get; }

        public Bar1(ref FooSettings settings)
        {
            Settings = settings;
        }

        public void WriteTag()
        {
            Console.WriteLine("Bar1 " + Settings.Tag);
        }
    }

    public class Bar2
    {
        private FooSettings Settings { get; }

        public Bar2(ref FooSettings settings)
        {
            Settings = settings;
        }

        public void WriteTag()
        {
            Console.WriteLine("Bar2 " + Settings.Tag);
        }
    }
}

Upvotes: 0

Views: 258

Answers (3)

Praveen M
Praveen M

Reputation: 453

I can suggest you following changes .

You can have a base class for FooMethods , something like FooMethodsBaseClass which will be parent class for Bar1 and Bar2 .

You can move all your common codes, methods to base class and Bar1 and Bar2 can access those .

This way you can segregate the code . And in future, if you get requirement in which you have to implement in both in Bar1 and Bar2 you can add it in single place, in base class. Thus you can avoid duplicates .

As you can see WriteTag i made it as virtual . And overridden by child classes

Also passing as ref is not needed

Further more, you can have interface for FooMethodsBaseClass. This will actually help you in writing unit tests

Base Interface :

 public interface IFooMethodsBaseClass
    {
        void WriteTag();
    }

Base class:

    public class FooMethodsBaseClass:IFooMethodsBaseClass
    {
        protected IFooSettings Settings { get; }

        public FooMethodsBaseClass(IFooSettings settings)
        {
            Settings = settings;
        }

        public virtual void WriteTag()
        {

        }
    }

Bar1 class

public class Bar1: FooMethodsBaseClass
{
    public Bar1(IFooSettings fooSettings):base(fooSettings)
    {

    }

    public override void WriteTag()
    {
        Console.WriteLine("Bar1 " + Settings.Tag);
    }
}

Bar2 Class

public class Bar2: FooMethodsBaseClass
{
    public Bar2(IFooSettings fooSettings):base(fooSettings)
    {

    }

    public override void WriteTag()
    {
        Console.WriteLine("Bar2 " + Settings.Tag);
    }
}

Foo and Foo Settings . Foo settings can be derived from interface as well. Since you are creating Foo by passing FooSettings , by introducing interface based injection you can write unit tests without any dependency by mocking

    public class Foo
    {
        public IFooSettings Settings;

        public IFooMethodsBaseClass Bar1 { get; }
        public IFooMethodsBaseClass Bar2 { get; }

        public Foo(IFooSettings settings)
        {
            Settings = settings;
            Bar1 = new Bar1(Settings);
            Bar2 = new Bar2(Settings);
        }
    }

    public class FooSettings: IFooSettings
    {
        public string Tag { get; set; }

        public FooSettings(string tag)
        {
            Tag = tag;
        }

    }

    public interface IFooSettings
    {
        string Tag { get; set; }
    }

Finally you can create Foo instance like this

 IFooSettings fs = new FooSettings("1");
 Foo foo = new Foo(fs);

Upvotes: 2

Vilx-
Vilx-

Reputation: 106920

Ok, so this actually seems pretty fine. A few tweaks I would make myself:

  • There's not much need for child classes here - I would use namespaces instead. Makes it easier to write.
  • There's no need for the ref qualifier in the BarX constructors.
  • BarX classes could be lazily instantiated when someone first accesses Foo.BarX. When using such huge APIs, the typical use case will probably just use a few methods, so most BarXs will never be needed.
  • Make Foo.Settings readonly, either through a property or just with a readonly qualifier.
  • Optionally, pass the Foo instance to the BarX instead of the settings. BarX can access the settings (and more if needed) through that.

Upvotes: 1

Igor Chepik
Igor Chepik

Reputation: 89

May be to make the settings a static field?

        public class Foo
        {
            public static FooSettings Settings;

            public FooMethods.Bar1 Bar1 { get; private set; }
            public FooMethods.Bar2 Bar2 { get; private set; }

            public Foo(FooSettings settings)
            {
                Settings = settings;
                Bar1 = new FooMethods.Bar1();
                Bar2 = new FooMethods.Bar2();
            }
        }

        public class FooSettings
        {
            public string Tag { get; set; }

            public FooSettings(string tag)
            {
                Tag = tag;
            }
        }

        public class FooMethods
        {
            public class Bar1
            {
                public void WriteTag()
                {
                    Console.WriteLine("Bar1 " + Foo.Settings.Tag);
                }
            }

            public class Bar2
            {
                public void WriteTag()
                {
                    Console.WriteLine("Bar2 " + Foo.Settings.Tag);
                }
            }
        }

And methods bar1 and bar2 can be implemented by the one class. Or its just for example?

Upvotes: 0

Related Questions