1

I have multiple classes in a project that are exactly the same except for the name of the class. Basically, they represent glorified enums loaded at runtime from config files. The classes look like this:

public class ClassName : IEquatable<ClassName> {
    public ClassName(string description) {
        Description = description;
    }

    public override bool Equals(object obj) {
        return obj != null &&
            typeof(ClassName).IsAssignableFrom(obj.GetType()) && 
            Equals((ClassName)obj);
    }

    public bool Equals(ClassName other) {
        return other != null && 
            Description.Equals(other.Description);
    }

    public override int GetHashCode() {
        return Description.GetHashCode();
    }

    public override string ToString() {
        return Description;
    }

    public string Description { get; private set; }
}

I see no reason to copy this file and change the class name multiple times. Surely there's a way I can just list what classes I want and have them automatically created for me. How?

Instance Hunter
  • 7,837
  • 5
  • 44
  • 56
  • 1
    Why wouldn't normal class inheritance work? Then the only thing you would repeat would be the constructor. – David Jan 06 '10 at 14:55
  • I don't want classes of one type like this to be comparable with classes of another type like this. Inheritance can handle GetHashCode, ToString and Description, but not Equals. – Instance Hunter Jan 06 '10 at 14:57
  • I'm not saying this applies specifically to your situation, but, anytime I think "How can I quickly duplicate this X times" it raises a big red flag telling me to reconsider my design. Usually, I try to remove duplication rather than automate it. – Eric King Jan 06 '10 at 15:20

5 Answers5

12

I'd suggest using T4. A substantial advantage of this over code snippets is that if you change your template then all of your code will be updated to match.

Put this in a file with the extension .tt

<#@ template language="C#" #>
<#@ output extension=".codegen.cs" #>
<#@ assembly name="System.dll" #>
<#@ import namespace="System" #>
// <auto-generated>
// This code was generated by a tool. Any changes made manually will be lost
// the next time this code is regenerated.
// </auto-generated>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyStuff
{
<# foreach (string classname in classes) {#>
    public class <#= classname #> : IEquatable<ClassName> 
    {
            public <#= classname #>(string description) {
        Description = description;
    }

    public override bool Equals(object obj) {
        return obj != null &&
            typeof(<#= classname #>).IsAssignableFrom(obj.GetType()) && 
            Equals((<#= classname #>)obj);
    }

    public bool Equals(<#= classname #>other) {
        return other != null && 
            Description.Equals(other.Description);
    }

    public override int GetHashCode() {
        return Description.GetHashCode();
    }

    public override string ToString() {
        return Description;
    }

    public string Description { get; private set; }
    }
    }

<# } #> 
}

<#+ string[] classes = new string[] {  "Class1",
                                       "Class2" };
#>

VS will generate a source file for you. Just add to the array classes when you need a new class.

Craig Stuntz
  • 125,891
  • 12
  • 252
  • 273
  • Supported in express by any chance? – Instance Hunter Jan 06 '10 at 15:04
  • If T4 will get VS to generate the source files for you I'm going to have to stop using my homebrew c# tool to create simple codefiles now! Thx for the example Craig – Tj Kellie Jan 06 '10 at 15:05
  • 1
    Daniel, yes, you can do this in Express with some configuration. See this question: http://stackoverflow.com/questions/786734/subsonic-asp-net-mvc-sample-in-visual-web-developer-express – Craig Stuntz Jan 06 '10 at 15:08
3

Could you use inheritance with generics?

public class MyBase<T> : IEquatable<MyBase<T>>
    where T : MyBase
{
    public ClassName(string description) {
        Description = description;
    }

    public override bool Equals(object obj) { ... }

    public bool Equals(T other) {
        return other != null && 
            Description.Equals(other.Description);
    }

    public override int GetHashCode() { ... }

    public override string ToString() { ... }

    public string Description { get; private set; }
}

Then you could inherit like this:

public class ClassName1 : MyBase<ClassName1> { ... }
public class ClassName2 : MyBase<ClassName2> { ... }
public class ClassName3 : MyBase<ClassName3> { ... }
Arjan Einbu
  • 13,543
  • 2
  • 56
  • 59
2

Have you considered code snippets?

CesarGon
  • 15,099
  • 6
  • 57
  • 85
1

If the classes really are the exact same, could you just use inheritance? The amount of code is pretty small and it doesn't require any extra pre/post processing.

public class Equatable : IEquatable { ... }

public class ClassName1 : Equatable {}
public class ClassName2 : Equatable {}
public class ClassName3 : Equatable {}
public class ClassName4 : Equatable {}

NOTE: All of the code snippet suggestions seem like they would be a maintenance nightmare down the road if you needed to change something.

Alan Jackson
  • 6,361
  • 2
  • 31
  • 32
0

I would suggest you to create code snippet yourself, that will be quick and easy.

Prashant Cholachagudda
  • 13,012
  • 23
  • 97
  • 162