Skip to main content
deleted 26 characters in body
Source Link
Jamal
  • 34.9k
  • 13
  • 133
  • 237

I find myself frequently converting between formats, so I have come up with the following conversion framework:

. The converter interface surfaces a method to convert from a source type to a target type.

The factory is for producing concrete converters.:

This next interface allows for the implementation of a generic converter that you can inject into a class and reuse for many conversions of different types (you can inject the factory instead but the code just looks cleaner with the generic converter).:

Lets look atHere's a simple example to illustrate how to implement these interfaces are implemented. First I will look at the factory as we can provide a pretty generic factory implementation.

The factory implementation introduces a dictionary to keep track of registered converters and the associated constructors for the converters. A registration method is added to allow registration of converters. And finally GetConverterGetConverter is implemented to look up the converter from the dictionary.

The generic converter can be implemented with a dependency on this factory like so:

Inject a factory into the constructor and then ConvertConvert can be called for any conversion and the class will get a converter from the factory, run the converter and return the result of the conversion.

Lets introduceHere are some models NOTE:. Note the POCO models, noabsence of dependencies, completely different signatures and very cleancleanliness.

So the plan is to convert from DogDescriptorDogDescriptor to DogDog and from CatDescriptorCatDescriptor to CatCat. The converters need to implement IConverterIConverter.

Now we have all the bits and pieces we need to do a conversion.:

        var factory = new ConverterFactory();

        // register converters
        factory.RegisterConverter<DogDescriptor, Dog>(() => new DogConverter());
        factory.RegisterConverter<CatDescriptor, Cat>(() => new CatConverter());


        var converter = new GenericConverter(factory);
        var dog = converter.Convert<DogDescriptor, Dog>(new DogDescriptor{Name = "Spot"});
        var cat = converter.Convert<CatDescriptor, Cat>(new CatDescriptor{Number = 666});

Extending conversion support is fairly easy, assumeassuming the two new models are introduced Duckas Duck and DuckDescriptorDuckDescriptor. All the developer needs to do is implement a DuckDescriptor to DuckDuckDescriptor-to-Duck converter and then register the converter with the factory.

The factory has no dependencies and can easily be tested. The The generic converter needs a mock factory injected for testing. Converters Converters only have dependencies on the models they convert which makes testing converters extremely easy.

  1. Am I reinventing the wheel? I couldn't find anything like it in the .NET framework but I also did not look very hard.

  2. Many conversion implementations extend the model classes with ToTypeToType style methods. Does this approach offer any advantages?

While I can see the attraction of this approach, it requires an extension method for every conversion which starts getting ugly when you have to do vendor specific conversions of the same models. Using the factory solution, you would simply implement vendor specific factories and inject a generic converter constructed with the vendor specific factory.

I find myself frequently converting between formats so I have come up with the following conversion framework:

The converter interface surfaces a method to convert from a source type to a target type.

The factory is for producing concrete converters.

This next interface allows for the implementation of a generic converter that you can inject into a class and reuse for many conversions of different types (you can inject the factory instead but the code just looks cleaner with the generic converter).

Lets look at a simple example to illustrate how to implement these interfaces. First I will look at the factory as we can provide a pretty generic factory implementation.

The factory implementation introduces a dictionary to keep track of registered converters and the associated constructors for the converters. A registration method is added to allow registration of converters. And finally GetConverter is implemented to look up the converter from the dictionary.

The generic converter can be implemented with a dependency on this factory like so

Inject a factory into the constructor and then Convert can be called for any conversion and the class will get a converter from the factory, run the converter and return the result of the conversion.

Lets introduce some models NOTE: POCO models, no dependencies, completely different signatures and very clean.

So the plan is to convert from DogDescriptor to Dog and from CatDescriptor to Cat. The converters need to implement IConverter.

Now we have all the bits and pieces we need to do a conversion.

        var factory = new ConverterFactory();

        // register converters
        factory.RegisterConverter<DogDescriptor, Dog>(() => new DogConverter());
        factory.RegisterConverter<CatDescriptor, Cat>(() => new CatConverter());


        var converter = new GenericConverter(factory);
        var dog = converter.Convert<DogDescriptor, Dog>(new DogDescriptor{Name = "Spot"});
        var cat = converter.Convert<CatDescriptor, Cat>(new CatDescriptor{Number = 666});

Extending conversion support is fairly easy, assume two new models are introduced Duck and DuckDescriptor. All the developer needs to do is implement a DuckDescriptor to Duck converter and then register the converter with the factory.

The factory has no dependencies and can easily be tested. The generic converter needs a mock factory injected for testing. Converters only have dependencies on the models they convert which makes testing converters extremely easy.

  1. Am I reinventing the wheel? I couldn't find anything like it in the .NET framework but I also did not look very hard.

  2. Many conversion implementations extend the model classes with ToType style methods. Does this approach offer any advantages?

While I can see the attraction of this approach it requires an extension method for every conversion which starts getting ugly when you have to do vendor specific conversions of the same models. Using the factory solution you would simply implement vendor specific factories and inject a generic converter constructed with the vendor specific factory.

I find myself frequently converting between formats, so I have come up with the following conversion framework. The converter interface surfaces a method to convert from a source type to a target type.

The factory is for producing concrete converters:

This next interface allows for the implementation of a generic converter that you can inject into a class and reuse for many conversions of different types (you can inject the factory instead but the code just looks cleaner with the generic converter):

Here's a simple example to illustrate how these interfaces are implemented. First I will look at the factory as we can provide a pretty generic factory implementation.

The factory implementation introduces a dictionary to keep track of registered converters and the associated constructors for the converters. A registration method is added to allow registration of converters. And finally GetConverter is implemented to look up the converter from the dictionary.

The generic converter can be implemented with a dependency on this factory like so:

Inject a factory into the constructor and then Convert can be called for any conversion and the class will get a converter from the factory, run the converter and return the result of the conversion.

Here are some models. Note the POCO models, absence of dependencies, completely different signatures and cleanliness.

So the plan is to convert from DogDescriptor to Dog and from CatDescriptor to Cat. The converters need to implement IConverter.

Now we have all the bits and pieces we need to do a conversion:

var factory = new ConverterFactory();

// register converters
factory.RegisterConverter<DogDescriptor, Dog>(() => new DogConverter());
factory.RegisterConverter<CatDescriptor, Cat>(() => new CatConverter());


var converter = new GenericConverter(factory);
var dog = converter.Convert<DogDescriptor, Dog>(new DogDescriptor{Name = "Spot"});
var cat = converter.Convert<CatDescriptor, Cat>(new CatDescriptor{Number = 666});

Extending conversion support is fairly easy, assuming the two new models are introduced as Duck and DuckDescriptor. All the developer needs to do is implement a DuckDescriptor-to-Duck converter and then register the converter with the factory.

The factory has no dependencies and can easily be tested. The generic converter needs a mock factory injected for testing. Converters only have dependencies on the models they convert which makes testing converters extremely easy.

  1. Am I reinventing the wheel? I couldn't find anything like it in the .NET framework but I also did not look very hard.

  2. Many conversion implementations extend the model classes with ToType style methods. Does this approach offer any advantages?

While I can see the attraction of this approach, it requires an extension method for every conversion which starts getting ugly when you have to do vendor specific conversions of the same models. Using the factory solution, you would simply implement vendor specific factories and inject a generic converter constructed with the vendor specific factory.

deleted 4 characters in body; edited title
Source Link
Jamal
  • 34.9k
  • 13
  • 133
  • 237

C# Generic Converter framework

C# Generic Converter framework

C# Generic Converter framework

Generic Converter framework

Source Link
Hawk
  • 233
  • 2
  • 5

C# Generic Converter framework

I find myself frequently converting between formats so I have come up with the following conversion framework:

The converter interface surfaces a method to convert from a source type to a target type.

public interface IConverter<in TSource, out TTarget>
{
    TTarget Convert(TSource source);
}

The factory is for producing concrete converters.

public interface IConverterFactory
{
    IConverter<TSource, TTarget> GetConverter<TSource, TTarget>();
}

This next interface allows for the implementation of a generic converter that you can inject into a class and reuse for many conversions of different types (you can inject the factory instead but the code just looks cleaner with the generic converter).

public interface IGenericConverter
{
    TTarget Convert<TSource, TTarget>(TSource source);
}

Lets look at a simple example to illustrate how to implement these interfaces. First I will look at the factory as we can provide a pretty generic factory implementation.

public class ConverterFactory : IConverterFactory
{
    private readonly Dictionary<Tuple<Type, Type>, Func<object>> _converters =
        new Dictionary<Tuple<Type, Type>, Func<object>>();

    public void RegisterConverter<TSource, TTarget>(Func<object> constructor)
    {
        _converters.Add(new Tuple<Type, Type>(typeof(TSource), typeof(TTarget)), constructor);
    }

    public IConverter<TSource, TTarget> GetConverter<TSource, TTarget>()
    {
        var constructor = _converters[new Tuple<Type, Type>(typeof (TSource), typeof (TTarget))];
        return (IConverter<TSource, TTarget>) constructor();
    }
}

The factory implementation introduces a dictionary to keep track of registered converters and the associated constructors for the converters. A registration method is added to allow registration of converters. And finally GetConverter is implemented to look up the converter from the dictionary.

The generic converter can be implemented with a dependency on this factory like so

public class GenericConverter : IGenericConverter
{
    private readonly ConverterFactory _factory;

    public GenericConverter(ConverterFactory factory)
    {
        _factory = factory;
    }

    public TTarget Convert<TSource, TTarget>(TSource source) 
    {
        var converter = _factory.GetConverter<TSource, TTarget>();
        return converter.Convert(source);
    }
}

Inject a factory into the constructor and then Convert can be called for any conversion and the class will get a converter from the factory, run the converter and return the result of the conversion.

Lets introduce some models NOTE: POCO models, no dependencies, completely different signatures and very clean.

public class Dog
{
    public string Name { get; set; }
}

public class DogDescriptor
{
    public string Name { get; set; }
}

public class Cat
{
    public int Number { get; set; }
}

public class CatDescriptor
{
    public int Number { get; set; }
}

So the plan is to convert from DogDescriptor to Dog and from CatDescriptor to Cat. The converters need to implement IConverter.

public class DogConverter : IConverter<DogDescriptor, Dog>
{
    public Dog Convert(DogDescriptor descriptor)
    {
        return new Dog {Name = descriptor.Name};
    }
}

public class CatConverter : IConverter<CatDescriptor, Cat>
{
    public Cat Convert(CatDescriptor descriptor)
    {
        return new Cat {Number = descriptor.Number};
    }
}

Now we have all the bits and pieces we need to do a conversion.

        var factory = new ConverterFactory();

        // register converters
        factory.RegisterConverter<DogDescriptor, Dog>(() => new DogConverter());
        factory.RegisterConverter<CatDescriptor, Cat>(() => new CatConverter());


        var converter = new GenericConverter(factory);
        var dog = converter.Convert<DogDescriptor, Dog>(new DogDescriptor{Name = "Spot"});
        var cat = converter.Convert<CatDescriptor, Cat>(new CatDescriptor{Number = 666});

Ideally you will use dependency injection to inject the generic converter into any classes that need to do conversions. Your dependency injection solution can then be configured to run the generic converter as a singleton.

Extending conversion support is fairly easy, assume two new models are introduced Duck and DuckDescriptor. All the developer needs to do is implement a DuckDescriptor to Duck converter and then register the converter with the factory.

The factory has no dependencies and can easily be tested. The generic converter needs a mock factory injected for testing. Converters only have dependencies on the models they convert which makes testing converters extremely easy.

Questions

  1. Am I reinventing the wheel? I couldn't find anything like it in the .NET framework but I also did not look very hard.

  2. Many conversion implementations extend the model classes with ToType style methods. Does this approach offer any advantages?

While I can see the attraction of this approach it requires an extension method for every conversion which starts getting ugly when you have to do vendor specific conversions of the same models. Using the factory solution you would simply implement vendor specific factories and inject a generic converter constructed with the vendor specific factory.