HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

How could I reduce repetition with properties/methods?

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
howwithpropertiescouldmethodsreducerepetition

Problem

I'm serializing instances of a lot of classes (in C# 3.0), and I've found myself writing this:

[DataContract]
public class ModelClass
{
    public static Guid GetID(ModelClass instance) { ... }

    public static T FromID(Guid value) where T : ModelClass { }

    [DataMember] public Guid m_id { get; set; }
}

[DataContract]
public class ConcreteModel: ModelClass
{
    [DataMember]
    public string      m_name;

    // Stuff we don't serialize
    public Sector      m_sector;
    public Theater     m_theater;
    public Weather     m_weather;
    public TerrainType m_terrainType;

    // Link serialized ids to real objects through GetID & FromID
    [DataMember] private Guid m_sectorID
    {
        get { return GetID(m_sector); }
        set { m_sector = FromID(value); }
    }

    [DataMember] private Guid m_theaterID
    {
        get { return GetID(m_theater); }
        set { m_theater = FromID(value); }
    }

    [DataMember] private Guid m_weatherID
    {
        get { return GetID(m_weather); }
        set { m_weather = FromID(value); }
    }

    [DataMember] private Guid m_terrainTypeID
    {
        get { return GetID(m_terrainType); }
        set { m_terrainType = FromID(value); }
    }
}


ConcreteModel is just one of many (~100) classes that will have some objects that are going to be saved using IDs, but not the whole objects, so we'll have to write that kind of properties a lot of times.

Is there any way of avoiding this? In C++ I'd be using macros, but not in C#...

My main concern here is not writing those properties all over again like 500 times or more. Any idea on how could I avoid that?

Solution

As @Magus commented, this is as good as it gets.

...almost.

[DataContract]
public class ConcreteModel: ModelClass


[DataMember] public Guid m_id { get; set; }


[DataMember]
public string      m_name;


You're not consistent with how you're placing your DataMemberAttribute attributes; sometimes they're sitting on top of the decorated member, other times they're stuck in front, on the same line. I'd stick to consistently having them on top.

// Stuff we don't serialize
public Sector      m_sector;
public Theater     m_theater;
public Weather     m_weather;
public TerrainType m_terrainType;


Why are these fields public in the first place? You are breaking encapsulation!

[DataMember] private Guid m_sectorID
{
    get { return GetID(m_sector); }
    set { m_sector = FromID(value); }
}


I'm not familiar with serialization using [DataMemberAttribute], but it's rather odd that you expose public fields and declare private serializable properties. Since the fields are exposed anyway, why not just do this?

private Sector m_sector;

[DataMember]
public Guid m_sectorID
{
    get { return GetID(m_sector); }
    set { m_sector = FromID(value); }
}


The naming is, as @Magus commented already, breaking all C# naming conventions. Drop the m_ prefix, and use PascalCase for public members:

private Sector _sector; // or just "sector"

[DataMember]
public Guid SectorId
{
    get { return GetId(_sector); }
    set { _sector = FromId(value); }
}


If ModelClass isn't intended to be instantiated and only serve as a base class, you should make it abstract - also "Class" at the end of a class name is rather useless. How about this?

public abstract class ModelBase


The public static members could made non-static, and be protected so as to only be exposed to the derived types.

Code Snippets

[DataContract]
public class ConcreteModel: ModelClass
[DataMember] public Guid m_id { get; set; }
[DataMember]
public string      m_name;
// Stuff we don't serialize
public Sector      m_sector;
public Theater     m_theater;
public Weather     m_weather;
public TerrainType m_terrainType;
[DataMember] private Guid m_sectorID
{
    get { return GetID(m_sector); }
    set { m_sector = FromID<Sector>(value); }
}

Context

StackExchange Code Review Q#48801, answer score: 2

Revisions (0)

No revisions yet.