43

I'm looking for a way to accelerate a repeatable task when I write code. I have ReSharper and I'm thinking a customization could do what I need.

I have two objects of the same type. I want to copy all of the public properties of one object to the other object. I want the tool, ReSharper in this case, to do generate the code for me. I'll tell it the names of the first object and the second object. I want it to find all the public properties of the first object and copy the values to the second object.

Here's the type of code I'm looking to have generated with a tool like ReSharper:

foo.Name = moo.Name;
foo.Age = moo.Age;
foo.City = moo.City;

Automating this simple code that copies values from right to left would save a ton of time and I'm thinking that ReSharper can do it. However, I haven't seen anything pop-up in searches for it though.

I'm not looking for a CodeSmith code generation technique or T4 template because I only want it to generate these specific lines inside my class, not generate and entire class or a separate file.

Does anyone know a way to press a few keystrokes, enter the "foo" and "moo" object names above and have the tool generate these copy from right to left lines of code?

Update:

I've found some documentation on building extensions to ReSharper, and this can probably be achieved by that path, but it looks really involved.

http://www.jetbrains.net/confluence/display/ReSharper/PowerToys+Pack+3.0+User+Guide

This is beginning to look like a weekend challenge unless someone else has already written it.

a7drew
  • 7,801
  • 6
  • 38
  • 39

8 Answers8

70

It's really easy. ReSharper doesn't do it, but you can use a super duper REGEX!

In Visual Studio:

    public string Email { get; set; }
    public string CellPhone { get; set; }
    public int NumChildren { get; set; }
    public DateTime BirthDate { get; set; }
  1. Select all your properties. Hit CTRL-D to copy down.

  2. Now hit CTRL-H to replace. Make sure .* is selected for Regex matching.

  3. Replace: public [\w?]* (\w*) .* (This Regex may need to be tweaked)

  4. With: dest.$1 = source.$1;

Now you have some beautiful code you can put in a method of your choosing:

    dest.Email = source.Email;
    dest.CellPhone = source.CellPhone;
    dest.NumChildren = source.NumChildren;
    dest.BirthDate = source.BirthDate;

EDIT: New alternatives

  1. You can use AutoMapper for dynamic runtime mapping.
  2. Mapping Generator is really nice for static mapping. It can generate the code above and it works well with R#.
Jess
  • 23,901
  • 21
  • 124
  • 145
12

This is somewhat derivative from answer by @Jess (his regex didn't work for me on VS2013) but instead of using Visual Studio I am using regex101

Click link above and just paste your properties into Test string field and you will get them mapped.

Regex I used

public [A-Za-z\?]* ([A-Za-z0-9]*) .*

and replace

Dest.$1 = Source.$1

hope this saves you some time.

Matas Vaitkevicius
  • 58,075
  • 31
  • 238
  • 265
  • Hi Matas. Yes, I allowed for nullable types and broke the regex in my answer. Now it is fixed. Thanks. – Jess Mar 18 '15 at 12:55
9

I don't believe Resharper can do this, but Open Source AutoMapper can. New to AutoMapper? Check out the Getting Started page.

Ben Griswold
  • 17,793
  • 14
  • 58
  • 60
  • I had never heard of this tool. With data access layers and Data Contracts making this kind of code a necessity, this is a great tool! – Vaccano Aug 04 '09 at 15:58
  • 2
    Automapper is definitely a great thing for some cases, but can be VERY slow for large amounts of objects. – Telavian Mar 28 '14 at 17:30
  • 18
    We used Automapper in a large enterprise app with a ton of DTOs and after 6 months we abandoned it because it was harder to maintain and debug than the plain old assignment of the properties. Shouldn't be considered a big hit against AM but in the end we just wanted to break on a line of code instead of read out a large error message (The error message was accurate and useful). – TheDev6 Jun 24 '14 at 23:02
  • 5
    Same experience as TheDev6, we found that using automapper basically just delays the pain till later but with continuous pain till its removed. Hence why I'm reading this thread hoping someone has a basic boiler code generator :D – Choco Smith Apr 01 '15 at 07:05
  • 2
    I second @TheDev6 . AutoMapper is not trivial to setup for complex mapping scenarios and you need to run the web app or application just to see if it worked. Very slow development process compared to getting compile errors immediately. As much as I hate manual entry, it always works and saved me a lot of time in the end. – angularsen Jun 15 '15 at 20:50
4

I agree with @Ben Griswold.
In most situations, Automapper is the way to go.

But when you truly want to generate code that copies properties from one object to another, try this:

  1. Create a brand new class and derive from the class from which you want to copy properties.
  2. Right-click on this new derived class and click 'Refactor > Extract Interface'.
  3. Check all properties that you wish to copy.
  4. Choose 'Place beside' because this interface will be only temporary.
  5. Click 'Next'.
  6. Modify your derived class so that you are no longer inheriting from the base class and you are only implementing your new interface. Expect to see a red squiggle.
  7. Place your cursor over the red squiggle and hit 'ALT-ENTER' to 'Implement Members'.
  8. Click 'Finish'.
  9. Delete that temporary interface and modify your class so that you are no longer implementing it.
Jim G.
  • 15,141
  • 22
  • 103
  • 166
  • 2
    This only describes how to copy a type. Resharper can do it in one step using the -- wait for it -- the "Copy type" command. – disklosr Nov 28 '19 at 15:55
1

Based on @Matas answer I created a more robust version using regex101 that ignores generics, attributes and comments and normalizes spaces.

Regex: *((\/+.*\n*.*)|(\[.*\]\n*.*))*public [A-Za-z\_\?\<\>]* ([A-Za-z0-9\_]*).*(\n| )*

Replace: $4 = person.$4,\n

Markus
  • 3,871
  • 3
  • 23
  • 26
0

Here's a simple class to clone an object. It's not exactly what you asked for but perhaps this will be useful for you:

//.Net 2.0
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;

namespace YourNameSpace {
   public static class ObjectCloner {
      public static T Clone<T>(T obj) {
         using (MemoryStream buffer = new MemoryStream()) {
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(buffer, obj);
            buffer.Position = 0;
            T temp = (T)formatter.Deserialize(buffer);
            return temp;
         }
      }
   }
}
Chris Dunaway
  • 10,974
  • 4
  • 36
  • 48
-1

This is the kind of thing for which Cog shines. Basically, Cog is code generation tool. Code is generated via Python.

Brian
  • 25,523
  • 18
  • 82
  • 173
  • 6
    So, your suggesting the answer to my question is to use a Python program to help me write my C# code? Do you have an example of this? – a7drew Aug 04 '09 at 18:36
-2

Simply copying values from one side to the other is pretty ugly.

You might find it better to create a method to include in your classes that uses reflection to copy public properties. You could save this method in resharper to regenerate into other classes you need this functionality in.

Bryan Rowe
  • 9,185
  • 4
  • 26
  • 34