TOP KEK
TOP KEK

Reputation: 2651

Avoid dll dependencies in class

We have a class which translates user interface into several languages. Basic idea of this class is that it simply checks all controls on the form and read text values for each control from an xml file.

foreach(Control control in form.Controls)
{
    if (control is Label)
        ReadTextForLabel(control);
    else if (control is MySuperCoolLabel)
        ReadTextForMySuperCoolLabel(control);
    ...
}

So we tried to create a universal class for translating every control in our programs.

Some time ago we came to a problem that we have too many classes like MySuperCoolLabel from different libraries. If we want to translate interface in a new program using our translation class, we have to add all these dlls with our SuperCoolLabels even if there are no any SuperCoolLabels in the program.

The question is: how to avoid all these dependencies and still have one universal class to translate programs?

Upvotes: 0

Views: 162

Answers (4)

jgauffin
jgauffin

Reputation: 101150

Your problem is actually a violation of Liskovs Substitution Principle since your translation class must handle each derived type separately.

We know that winforms have to types of controls: Containers and Controls. A container contains several controls while a control is just a control ;)

We can use that knowlegde to create a universal form translator:

public class UniversalFormTranslater
{
    public void TranslateForm(System.Windows.Forms.ContainerControl container)
    {
        var name = container.Name;
        var originalText = container.Text;
        if (!string.IsNullOrEmpty(originalText))
            container.Text = Translate(name);

        TranslateControl(name, container);
    }

    private void TranslateControl(string parentName, System.Windows.Forms.ContainerControl control)
    {
        var name = parentName + "." + control.Name;
        var originalText = control.Text;
        if (!string.IsNullOrEmpty(originalText))
            control.Text = Translate(name);
    }

    private void TranslateControl(string parentName, System.Windows.Forms.ContainerControl container)
    {
        var name = parentName + "." + container.Name;
        var originalText = container.Text;
        if (!string.IsNullOrEmpty(originalText))
            container.Text = Translate(name);

        foreach (var control in container.Controls)
        {
            TranslateControl(name, control);
        }
    }

    public void Translate(string controlName)
    {
        // return the translation.
    }
}

It looks for strings like:

  • Form1.MyGroupPanel.Label1
  • Form1.MyTextBox

Translate by using:

var translator = new UniversalFormTranslater();
translator.TranslateForm(form1);

Upvotes: 0

Tigran
Tigran

Reputation: 62266

Well, dependencies are metter of the program architecture. To be clear:

I suppose you write ReadTextForMySuperCoolLabel(..) cause you need to translate some particular to that control properties, that you will not possibly met into other controls you use.

If this is true, there is no way to avoid the dependecy yuo're talking about. Use you direct assignment, use reflection, use somethig else... there have to be someone, somewhere that says: "this is a MySuperControl, so do this, this is other, so do that".

If there is a way generalize the property assignment. For example, all controls in your app could have Text property. In this case could make the stuff general.

Good luck.

Upvotes: 1

daryal
daryal

Reputation: 14919

Maybe you can try to distinguish controls not by type, but typenames as strings. something like;

if (control.GetType().ToString() == "Label")
    ReadTextForLabel(control);
else if (control.GetType().ToString() == "MySuperCoolLabel")
    ReadTextForMySuperCoolLabel(control);

On the other hand, I wonder why you did not use .Net builtin support for multi language.

Upvotes: 2

Aidan
Aidan

Reputation: 4901

Well, one way would be to late bind all your classes, either by using a dependency injection framwork (like Castle Windsor) or rolling your own by creating your classes like this :

var myCoolClass = Activator.CreateInstance(  typeof( MySuperCoolTextBox ) )

That way you won't need to add a reference to the SuperCool library, only include it with your binries. However, I am guessing that SuperCool controls are used in a form designer, so you might not be able to instatiate your controls like this.

Upvotes: 0

Related Questions