0

I have some DTOs with one parent. This parent has generic method to create any its child(uses reflection). Every of those DTOs has configuration(dictionary). I can pass the dictionary through parameters in the creating method but every child type has the same configuration so I would like to make it static and store in children. I found here: Accessing a static property of a child in a parent method that it can be a faulty design. Is it in my case? Do I have to pass the configuration through parameter or maybe store it somewhere else?

Example:

public class Parrent
{
    public static T Create<T>(string[] fields, Dictionary<string, bool> config) 
      where T : Parrent
    {
        var result = Activator.CreateInstance<T>();
        // filling fields using config
        return result
    }
}

EDIT:

Here's how does the config work:

public class Child1 : Parrent
{
    public string Child1String;
    public DateTime Child1DateTime;
}

public class Child2 : Parrent
{
    public int Child2Int;
    public string Child2String;
    public TimeSpan Child2TimeSpan;
}

and the dictionary(it says which fields I can ignore (because they will be empty for example) and it's set in processing class from a config file):

- Child1:

    "Child1String": true,
    "Child1DateTime": true,

- Child2

    "Child2Int": true,
    "Child2String": false,
    "Child2TimeSpan": true,
Vladel
  • 230
  • 1
  • 4
  • 16
  • 4
    Side note: why not `where T : Parrent, new()` and then `var result = new T();` instead of `Activator.CreateInstance()`? – Dmitry Bychenko Sep 20 '18 at 07:32
  • @DmitryBychenko Right, I can change it. Forgot about it. Thanks :) – TheMelancholicMan Sep 20 '18 at 07:33
  • " but every child type has the same configuration" what does it mean exactly? that each child has the same initial values for the same set of properties? – Mong Zhu Sep 20 '18 at 07:37
  • @MongZhu Yes. Let's say that I have `public class Child1 : Parrent` and `public class Child2 : Parrent` Then every instance of Child1 has the same config dictionary and every instance of Child2 has the same config dictionary but different than in Child1. – TheMelancholicMan Sep 20 '18 at 07:44
  • "every child type has the same configuration" and " but different than in Child1" confuses me a little. what is the dictionary good for? does it hold the field names and the corresponding values? Please post an example of 2 children and how the content of this dictionary might look like – Mong Zhu Sep 20 '18 at 07:50
  • is the configuration hard coded ? or do you get them from an external source? file / data table ect – Mong Zhu Sep 20 '18 at 07:55
  • @MongZhu Answered below – TheMelancholicMan Sep 20 '18 at 07:58

1 Answers1

0

A class should not assume anything about its inheritors other than what it explicitly obliges in the definition of the type.

It is definitely a "code smell" to use reflection so a parent can interact with its children. This sounds like a way to push what should be static design problems to run time.

If you want to populate children with some config, you'll need to ensure those properties exist in their implementation. Alternatively, you can delegate to the children my making the config method abstract. Use virtual for a combination of the two.

public class Parent
{
    public string PropertyParentControls { get; protected internal set; }

    static internal T ReadConfigItem<T>(
            string name,
            IReadOnlyDictionary<string, dynamic> configuration)
    {
        if (configuration.TryGetValue(name, out var configValue))
        {
            return configValue; 
        }
        else
        {
            return default(T);
        }
    }

    virtual internal void FillConfig(IReadOnlyDictionary<string, dynamic> configuration)
    {
        this.PropertyParentControls =
            ReadConfigItem<string>("PropertyParentControls", configuration);    
    }   
}

public sealed class Child : Parent
{
    public int PropertyChildControls { get; private set; }

    override internal void FillConfig(IReadOnlyDictionary<string, dynamic> configuration)
    {
        base.FillConfig(configuration); // because the Child wants the Parents help.
        this.PropertyChildControls = 
            ReadConfigItem<int>("PropertyChildControls", configuration);
    }
}
Jodrell
  • 34,946
  • 5
  • 87
  • 124