1

I have the following extension method in order for down-casting, mapping parent's properties to child with AutoMapper

using AutoMapper; /**/

public static TChild Downcast<TChild, TParent>(this TParent parent) {

    var config = new MapperConfiguration(c => c.CreateMap<TParent, TChild>());
    var mapper = config.CreateMapper();

    return mapper.Map<TChild>(parent);
}

It works pretty well as expected (sample usage):

 var parent = new Parent{ Name = "Bob" };
 var child = parent.Downcast<Child, Parent>();
 ...
 Assert.AreEqual(parent.Name, child.Name);

What I'm curious about is, I feel like there should be some way to actually have information about the compile time type of parent, without supplying it, after all, the class is where I call from, and it is-(should be) known at compile time.

So are there any way that I'd simplify this into something such:

public static TChild Downcast<TChild>(this TParent parent) where TParent : caller {

    var config = new MapperConfiguration(c => c.CreateMap<TParent, TChild>());
    var mapper = config.CreateMapper();

    return mapper.Map<TChild>(parent);
}

And use it such:

var child = parent.Downcast<Child>();

Thank you for your time.

Emirhan Özlen
  • 474
  • 2
  • 14
  • Well, if you have `object` as argument, you *don´t* know the exact type at *compile-time*, but at *runtime*. However you can of course infer the correct type at runtime using reflection. – MakePeaceGreatAgain Jan 18 '18 at 13:04
  • You're right. It was just to give an idea of what I'm trying to accomplish. To make extension method appear across all classes. – Emirhan Özlen Jan 18 '18 at 13:05
  • The possible duplicate you've marked was implying on run-time. I know I can do it with reflections. I'm just curious about my statement that's all. – Emirhan Özlen Jan 18 '18 at 13:08
  • @HimBromBeere please check out the the answer I've posted – Emirhan Özlen Jan 18 '18 at 13:36
  • This method signature `TChild Downcast(this TParent parent)` is obviously impossible, since `TParent` could never be resolved compile-time. You need to have `TParent` in the generic type constraint parameter in order for it to compile. But I understand your feeling to not want to provide the parent type twice. However unfortunately trying to achieve that method signature is impossible. – QuantumHive Jan 18 '18 at 14:14

1 Answers1

1

I solved this with introducing a middle struct, structure to casting:

public static Downcasting<TParent> Downcast<TParent>(this TParent parent) {

    return new Downcasting<TParent>(parent);
}

public struct Downcasting<TParent> {

    private readonly TParent parent;

    public Downcasting(TParent parent) { this.parent = parent; }

    public TChild To<TChild>() {

        var config = new MapperConfiguration(c => c.CreateMap<TParent, TChild>());
        var mapper = config.CreateMapper();

        return mapper.Map<TChild>(parent);
    }
}

This way I can make use of:

 var parent = new Parent{ Name = "Bob" };
 var child = parent.Downcast().To<Child>();
 ...
 Assert.AreEqual(parent.Name, child.Name);

However I'm still curious about for other possible solutions.

Emirhan Özlen
  • 474
  • 2
  • 14
  • 1
    That's a pretty creative solution and reads perfectly pleasant. An alternative could perhaps be consumed like this: `parent.Downcast(typeof(Child))`. However I'd prefer yours over readability. – QuantumHive Jan 18 '18 at 14:17