7

Is there a way to control the type conversion in C#? So for example, if I have two types with essentially the same details, but one is used for the internal working of my application and the other is a DTO used for communicating with non-.Net applications:

public sealed class Player
{
  public Player(string name, long score)
  {
    Name = name;
    Score = score;
    ID = Guid.NewGuid();
  }

  public string Name { get; private set; }

  public Guid ID { get; private set; }

  public long Score { get; private set; }
}

public sealed class PlayerDTO
{
  public PlayerDTO(string name, long score, string id)
  {
    Name = name;
    Score = score;
    ID = id;
  }

  public string Name { get; private set; }

  // the client is not .Net and doesn't have Guid
  public string ID { get; private set; }  

  public long Score { get; private set; }
}

Right now, I need to create a new instance of PlayerDTO from my Player instance every time and I'm looking for a better, cleaner way of doing this. One idea I had was to add an AsPlayerDTO() method to the player class, but would be nice if I can control the type conversion process so I can do this instead:

var playerDto = player as PlayerDTO; 

Anyone know if this is possible and how I might be able to do it?

Thanks,

theburningmonk
  • 15,701
  • 14
  • 61
  • 104

7 Answers7

5

You can implement an explicit convesion operator between the two types.

You could also consider using AutoMapper for the task.

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • Also +1 for AutoMapper. The "Getting Started" is almost exactly the OP's scenario. http://automapper.codeplex.com/wikipage?title=Getting%20Started&referringTitle=Documentation We use an extension method that allows you to do this: var playerDto = player.MapTo(); – Michael Meadows Feb 05 '10 at 16:04
3

You can implement either implicit or explicit type conversion: http://msdn.microsoft.com/en-us/library/ms173105.aspx.

Alternately, if you want to avoid making each class having to know about the other, you can use either custom mapping or an existing mapping library like AutoMapper.

Pete
  • 11,313
  • 4
  • 43
  • 54
  • Overloading the implicit/explicit operator seems to work for me and it's reasonably clean too. Curious though, this doesn't apply to arrays, but AutoMapper seems to give that option based on Michael Meadows' comment below. Is there a way to implement this without using 3rd extensions like AutoMapper? – theburningmonk Feb 05 '10 at 16:21
  • Never mind, found the answer to my second question on another stackoverflow question http://stackoverflow.com/questions/1865031/why-wont-castdouble-work-on-ienumerableint Array.ConvertAll(playerList.ToArray(), p => (PlayerDTO)p); – theburningmonk Feb 05 '10 at 16:29
  • 1
    Also, if you're using Linq, you can use Select... playerArray.Select(player => (PlayerDTO) player).ToArray(); – Michael Meadows Feb 05 '10 at 17:01
0

What about conversion operator:

public static explicit operator PlayerDTO (Player value)...
public static implicit operator PlayerDTO (Player value)...
Dewfy
  • 23,277
  • 13
  • 73
  • 121
0

You'll still have to do the code to create the DTO object, but you can overload the cast operator to cast from your implementation object to the DTO object. You can even make an implicit cast.

see overloading cast and implicit

Pete McKinney
  • 1,211
  • 1
  • 11
  • 21
0

You can use explicit type conversions.

public sealed class Player {
  public static explicit operator PlayerDTO(Player p) {
    PlayerDTO dto;
    // construct
    return dto;
  }
}

public sealed class PlayerDTO {
  public static explicit operator Player(PlayerDTO dto) {
    Player p;
    // construct
    return p;
  }
}
G-Wiz
  • 7,370
  • 1
  • 36
  • 47
0

Use AutoMapper @ http://www.codeplex.com/AutoMapper

epitka
  • 17,275
  • 20
  • 88
  • 141
0

Sounds like you should be using an interface.

Then cast to the interface: Example below

public interface IPlayer 
{
   string Name { get; set; }
}
public class Player : IPlayer 
{
   string Name { get; set; }
}

IPlayer playerDto = player as IPlayer;
Player player = Player(playerDto);

You would then use the IPlayer As the DTO object. I assume this is because the Player class does not exist in the other assembly and you do not want to more it. You could then use the IPlayer in a shared assembly... to transfer between assemblies.

Hope this helps... ;-)

Update

#

the Auto Mapper is a better route! I think

Seabizkit
  • 2,417
  • 2
  • 15
  • 32