Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write a converter class? How to efficiently write mapping rules?

I have a quite big class A with lots of members, and i have a quite big class B that can be built when having an A object. An A object can be built when having a B object. I need both of them, as A is a kind of ViewModel, which has validation and B is a graphical description, which can be plotted easily.

How to do this conversion?

here is an example, to illustrate what i want to do:

class A
{
    string s;
    string t;
    string u;
    string v;

    enum a;
    enum b;
    enum c;
    enum d;
    enum e;

    Dictionary<enum, string> dict;
}


class B
{
    string someString; // is essentially A.a + A.b + A.c + A.s with some rules.
    int someValue; // is essentially dict.TryGetValue(enum.Entry);
    string anotherString;
    // ... and lots of others
}

Of course it is simple to do some mapping, and build up a B object, and it is not very hard to write plain B => A mapping by inverting the rules of building A => B

So the questions are:

  • Are there any well known patterns to achieve that?
  • Is there a default C# way of doing such things?

Writing down plain something like that seems not to fit, it ends up in hundreds of lines of code.

I thought about some kind of converter classes for the parts, like SomeStringConverter, SomeValueConverter, ...

  • How can i abstract the needed members of A together with the rules to do the mapping.
  • How can i write those rules to have the easiest possible way of doing A => B and B => A.

Edit: Pattern here is meant as "Best practises" and not as "GoF design patterns"

SomeString in the B class is some kind of "selector", it selects drawing options, it is always 25 characters long and the enums in class A choose those characters, but not 1 on 1 in most cases.

Lets say for example: A.a = "Filled", A.b = "SingleCoordinate", A.c = "DrawHints" will result in something like SomeString =

 "Y**D***RR****---***---***"

i.e. the combination is important to get such an string, but from the combiniation you can derive the enums that have to be set in an A object.

Edit2:

I'm especially interested in ways of using my mapping rules for both ways, i.e. A.a = "Filled" combined with A.b = "SingleCoordinate" combinded with A.c = "DrawHints" will result in (partial string) "Y**D***RR", and that partial string also means that A.a has to be set to "Filled" and so on.

like image 496
Mare Infinitus Avatar asked Jun 26 '12 19:06

Mare Infinitus


2 Answers

Sounds to me like A is more of the Data Model and B is more of the View Model. I don't think there's a generally accepted "pattern" for this kind of instance—mainly because the reasons behind this kind of pairing vary widely and the best pattern is heavily dependent on intended use.

That said, since they're so tightly tied together, I'd tend to make one class subordinate to the other. In this case, since A is more straightforward, I'd probably use A as the data container for B. i.e. Have a private member A as a field in class B and all the properties in class B reference class A directly—updating properties in A rather than having their own private fields behind. You could then have a public property on class B that exposes the private member of class A if needed. I'd probably keep that read-only, but that's probably not really important (depending on your use of class B and any possible bound relationships). To go the other way, I'd then create a constructor on class B that accepts class A as a parameter. The passed value of A would then be assigned to the private class A member on class B.

The upshot of all that is to maintain class A's ignorance of class B—which becomes useful if you have a true use case for a ViewModel situation. If you determine that class A is the truer ViewModel in your needs, then reverse the above so that class B is the one ignorant of class A.

like image 166
Jacob Proffitt Avatar answered Oct 12 '22 02:10

Jacob Proffitt


Are there any well known patterns to achieve that?

It depends on what you mean by pattern. The Decorator or Adapter patterns come to mind, but neither is meant for wholesale mapping of types to different types.

Is there a default C# way of doing such things?

No, there isn't. But libraries like Automapper sure make life easier.

like image 35
Oded Avatar answered Oct 12 '22 02:10

Oded