0

I'm trying to design a simple conversion framework based on these requirements:

  1. All developers should follow a predefined set of rules to convert from the source entity to the target entity
  2. Some overall policies should be able to be applied in a central place, without interference with developers' code
  3. Both the creation of converters and usage of converter classes should be easy

To solve these problems in C# language, A thought came to my mind. I'm writing it here, though it doesn't compile at all. But let's assume that C# compiles this code:

I'll create a generic interface called IConverter

public interface IConverter<TSource, TTarget>
    where TSource : class, new()
    where TTarget : class, new()
{
    TTarget Convert(TSource source);

    List<TTarget> Convert(List<TSource> sourceItems);
}

Developers would implement this interface to create converters. For example:

public class PhoneToCommunicationChannelConverter : IConverter<Phone, CommunicationChannle>
{
    public CommunicationChannel Convert(Phone phone)
    {
        // conversion logic
    }

    public List<CommunicationChannel> Convert(List<Phone> phones)
    {
        // conversion logic
    }
}

And to make the usage of this conversion class easier, imagine that we add static and this keywords to methods to turn them into Extension Methods, and use them this way:

List<Phone> phones = GetPhones();
List<CommunicationChannel> channels = phones.Convert();

However, this doesn't even compile. With those requirements, I can think of some other designs, but they each lack an aspect. Either the implementation would become more difficult or chaotic and out of control, or the usage would become truly hard. Is this design right at all? What alternatives I might have to achieve those requirements?

1
  • Don't limit enumerable types to the List. Use IList or even IEnumerable instead. Aug 21, 2014 at 12:44

2 Answers 2

4

You could just define an explicit operator to the do the conversion right on the Phone class like so:

public class Phone 
{
     // your Phone props here

     public static explicit operator CommunicationChannel(Phone phone)
     {
          return new CommunicationChannel { PropQ = phone.PropZ };
     }
}

To use the operator, just cast Phone as CommunicationChannel:

List<Phone> phones = GetPhones();
List<CommunicationChannel> channels = phones.Select(phone => (CommunicationChannel)phone).ToList();
5
  • Except instead of using Select for that, you might try .Cast<CommunicationChannel>(). Of course, in neither case does this have anything to do with a conversion framework, which is the intent (though I'd admit I'd probably prefer to do it this way).
    – Magus
    Aug 21, 2014 at 14:39
  • 1
    Yep, '.Cast<>()' would be more terse. If there's only 1 way to convert from one type to another, a conversion framework seems like overkill, which is why I suggested this approach. Another approach would be to look at something like AutoMapper, which allows for mapping logic to be registered globally and re-used with very high performance for lots of type conversions.
    – GHP
    Aug 21, 2014 at 15:03
  • @Magus Except Cast() won't call overloaded cast operators, so it won't work here.
    – svick
    Aug 22, 2014 at 19:01
  • @svick: I had to go look that up, because it seemed insane. It's true! I do get why, though. Apparently the operator gets replaced at the call site :/.
    – Magus
    Aug 22, 2014 at 19:58
  • @Graham, thank you for answering. To use a third party library is not my concern here. That would be the first choice of course. I need to implement a conversion framework. A simple one, with the requirements I mentioned above. Aug 23, 2014 at 4:06
1

I had to specify a lot of custom type conversions in my project and had a lot of success just using a piece of code from the EmitMapper project

Emitmapper : StaticConvertersManager.cs

You can just create classes with static functions which have a param with one type and return another type and you can register these then with this manager

Saved me a lot of time

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.