0

I have several controller classes which use their own configuration classes that set controller classes behavior.

I have controller resolver that picks up desired controller by its name.

Now I want another resolver to bind controller class with its respective configuration class.

What I have now is configuration class nested in partial class of the same name as controller class so the resolver can determine the configuration class unambiguously, but I'm not very happy with this kind of monstrous solotion because the partial class containing only the nested configuration class has to have the same namespace as the controller class which bothers me the most because of its name inconsistency with the folder this class is physically located in as controller classes are in "Controller" folder and their namespaces are "Something.Controller" and configuration classes are in folder "Configuration" but their namespaces also have to be "Something.Controller".

//Path: .\Controller
namespace Something.Controller
{
    public partial class MyController : IController
    {
    }
}

//Path: .\Configuration
namespace Something.Controller
{
    public partial class MyController
    {
        public class MyControllerConfiguration : IConfiguration
        {
        }
    }
}

And the resolvers (no type validation as it's done earlier and the only types that can be passed to these methods already implement IController):

public class Resolver
{
    public IController GetController(Type controllerType)
    {
        return (IController)Activator.CreateInstance(controllerType);
    }
    public IConfiguration GetControllerConfiguration(Type controllerType)
    {
        var configurationType = controllerType.GetNestedTypes().FirstOrDefault(t => typeof(IConfiguration).IsAssignableFrom(t));
        if (configurationType != null)
            return (IConfiguration)Activator.CreateInstance(configurationType);
        else
            return null;
    }
}

So how can I couple controller class with its configuration class in some more clear way than nesting configuration class in its respective controller class?

EDIT:

Below some usage example:

Let's imagine I have two controllers. Each one has it's own configuration. Now I want to let the user choose which controller to use and then display to the user set of properties from the respective configuration class. Of course I could create the controller instance which would expose its configuration at the time when user sets up the application config but I don't believe it's a good idea.

Szybki
  • 1,083
  • 14
  • 29
  • how is the configuration class controlling the controller class's behaviour? –  May 10 '17 at 14:59
  • @Orangesandlemons Sets location of the file controller is working on, number of concurrent threads, etc. – Szybki May 10 '17 at 20:59

2 Answers2

0

This suggestion builds on the principle of Dependency Inversion. (The example in the post is actually closely related to this exact problem.)

The idea is that your controller shouldn't be responsible for determining where the configuration values come from. It should depend on an abstraction, like an interface.

The first thing I'd do is separate your settings into their own interface, like this: (this isn't plagiarism - it's my blog post.)

public interface IConfiguration
{
    string SomeSetting { get; }
    int OtherSetting { get; }
}

Then in your controller class, do this:

public class MyController
{
    private readonly IConfiguration _configuration;

    public MyController(IConfiguration configuration)
    {
        _configuration = configuration;
    }
}

Now, from the standpoint of the controller itself, the work is done. IConfiguration is required in the constructor, so it's impossible to create an instance of MyController without providing something that implements IConfiguration.

This is helpful because it encourages you to finish writing your controller without solving the problem of where the configuration settings will come from. You're deferring that. You can finish the task at hand and then decide how you want to implement IConfiguration. It can prevent the trivial task from sidetracking you from the more significant one.

And by design, MyController will never know what that implementation is. It does't care. It only depends on the interface. You can change where the settings come from without changing MyController, just by using a different implementation of IConfiguration. If you want to write unit tests for MyController and test it with different configuration settings, you can just write short "mocked" implementations of IConfiguration with hard-coded values.

That leaves the question of how IConfiguration gets passed into the constructor. That's often (or usually) done with a dependency injection container like Unity, Autofac, or Windsor. If you're using ASP.NET Core there's a built-in container. (I'm guessing this is an MVC controller but maybe it's not - it doesn't matter.)

To find instructions on how to configure your application to use a dependency injection container, Google the name of the technology you're using + " dependency injection", like "ASP.NET MVC dependency injection." Or if you mention what you're using I can point you to an article.

Dependency injection isn't a silver bullet, but for any complex application, including MVC apps, it can be extremely helpful. I found that it was a step toward understanding and applying other principles as well as learning to write unit tests. It also helped me avoid getting sidetracked. If the class I'm writing needs to depend on something else then I just write an interface for that dependency and keep working on the class I'm working on. Then I can go back and decide how to implement that dependency.

Scott Hannen
  • 27,588
  • 3
  • 45
  • 62
  • This is something I'm looking for. But the main problem is that every controller has its own configuration class. And there's nothing much to extract from those classes into an interface except the interface itself, which determines that class implementing it is a configuration class. Please see edit of the question, I've added some explanation. – Szybki May 10 '17 at 21:00
  • Even if each controller has its own configuration class I'm not sure what that would change. If you're using a DI container you're going to tell the container which implementation of any given interface to create. But "coupling" the two classes isn't beneficial. If you have two classes that are deliberately coupled and each only works with the other, why have two classes at all? – Scott Hannen May 10 '17 at 21:20
  • Actually the only reason of having two classes is that one class (which implements `IController`) is the class that "do stuff" and the other (which implements `IConfiguration`) is a set of properties that are set by user and stored/recalled on disk. – Szybki May 10 '17 at 21:27
  • Based on that... I'm still not sure that I see the inherit benefit in coupling them together. One of reasons to avoid coupling is because tightly coupled classes work until you have to change something. I'm not sure where unit testing fits in but depending on abstractions also makes unit testing easier. For example, if your settings always come from the hard drive, how will you test how the controller works with one setting vs. how it works with a different one? You'd have to actually write values to the hard drive to test your controller. – Scott Hannen May 10 '17 at 21:46
  • Actually, yes. I have to write them and the read from hard drive. Or set the values on the fly for test purposes. Anyway, suppose I would decouple configuration from the controller. The controller still needs its settings so it would need to do additional check if passed configuration is the configuration it is expecting. And it wouldn't be decoupled at all. Or should I redesign controllers to use only abstraction layer? – Szybki May 11 '17 at 07:18
  • The problem is that even if I had one controller it would still have to use some other layer to write processed data for example. And classes of that layer still need their settings, e.g. url/portnumber, portname/baudrate, filename, etc. And I don't want to serialize those classes as it seems not right for me. – Szybki May 11 '17 at 08:12
0

There are so many ways to do this.

For example in Spring framework the configuration can be done in separate XML file that populates each controller properties via "set" methods.

Another common approach is to have Controller to lookup its properties from some type of singleton PropertyManager that can have file, database or in memory implementation.

The question is, do you really need a separate configuration class for each controller or controller can also have the logic of getting its configuration from a separate configuration repository but at the same time not care how that repository is reading/writing its configurations.

tsolakp
  • 5,858
  • 1
  • 22
  • 28