JoeS
JoeS

Reputation: 1425

Reducing constructor boiler plate code

I often end up writing classes like this:

public class Animal
{
    public string Colour { get; set; }
    public int Weight { get; set; }

    public Animal(Dog data)
    {
        this.Colour = data.Colour;
        this.Weight = data.Weight;
    }

    public Animal(Cat data)
    {
        this.Colour = data.Colour;
        this.Weight = data.Weight;
    }
}

When you have lots of properties and types then you quickly end up with a lot of boiler plate code. Ideally in this situation I would just create an IAnimal interface and reference that. I'm currently in a situation where the Dog and Cat classes exist in a third party assembly and I can't modify them. The only solution that I can come up with is:

public class Animal
{
    public string Colour { get; set; }
    public int Weight { get; set; }

    public Animal(Cat data){Init(data);}
    public Animal(Dog data){Init(data);}

    private void Init(dynamic data)
    {
        this.Colour = data.Colour;
        this.Weight = data.Weight;
    }
}

This works but I lose all type safety, is there a better solution than constructor injection?

Thanks,

Joe

EDIT: Here is a real world example. I have a third party library which returns 3 objects called:

(These are all auto generated classes from a service reference and the properties are pretty much identical)

Instead of dealing with these three objects I want to deal with a single PageData object or a collection of them.

Upvotes: 7

Views: 820

Answers (4)

A.T.
A.T.

Reputation: 26312

try using json serializer's, with that we can ensure type safety.

 public class Animal
    {
        public string Colour { get; set; }
        public long Weight { get; set; }
        public string Name { get; set; }
        public Animal Create<T>(T anyType)
        {
            return GetObject<T, Animal>(anyType);
        }
        public K GetObject<T, K>(T type1)
        {
            try
            {
                var serialized = JsonConvert.SerializeObject(type1);
                return JsonConvert.DeserializeObject<K>(serialized);
            }
            catch (Exception ex)
            {
                return default(K);
            }
        }
    }
    class Program
    {
        public static void Main(string[] args)
        {
            Animal obj = new Animal();
            var animal = obj.Create(new  { Colour = "Red", Weight = 100 });
            //here you can pass any object, only same name properties will be initialized..
            Console.WriteLine(animal.Colour + " :  " + animal.Weight);
            Console.ReadKey();
        }
    }

Upvotes: 0

Dennis
Dennis

Reputation: 37770

I'm currently in a situation where the Dog and Cat classes exist in a third party assembly and I can't modify them

I'd suggest Automapper-based solution:

public static class AnimalFactory
{
    public static Animal Create<T>(T source)
        where T : class
    {
        Mapper.CreateMap<T, Animal>();
        return Mapper.Map<Animal>(source);
    }
}

Usage:

        var catAnimal = AnimalFactory.Create(cat);
        var dogAnimal = AnimalFactory.Create(dog);

Of course, you can provide a way to custom mapping configuration, if needed.

Upvotes: 4

James Brierley
James Brierley

Reputation: 4670

You can have the logic in one common constructor that all the other constructors call:

public class Animal
{
    public string Colour { get; set; }
    public int Weight { get; set; }

    public Animal(Dog data) : this (data.Colour, data.Weight)
    {
    }

    public Animal(Cat data) : this (data.Colour, data.Weight)
    {
    }

    private Animal(string colour, int weight)
    {
        this.Colour = colour;
        this.Weight = weight;
    }
}

This is pretty similar to your second solution but it doesn't lose type safety.

Upvotes: 4

David Pilkington
David Pilkington

Reputation: 13630

If you do not want to have the class littered like that you can try Extension methods?

public static Animal ToAnimal(this Dog item)
{
    return new Animal() {Weight = item.Weight, Colour = item.Colour};
}

public static Animal ToAnimal(this Cat item)
{
    return new Animal() {Weight = item.Weight, Colour = item.Colour};
}

Upvotes: 1

Related Questions