4
\$\begingroup\$

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<T>(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<Sector>(value); }
    }

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

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

    [DataMember] private Guid m_terrainTypeID
    {
        get { return GetID(m_terrainType); }
        set { m_terrainType = FromID<TerrainType>(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?

\$\endgroup\$
3
  • 2
    \$\begingroup\$ You're pretty much stuck here, unless you generate the code with a .tt or use Nemerle or F# (which could actually make sense: they certainly do have macros). This is mostly because you're declaring methods for each property. Roslyn may help eventually. Additionally, since this is CodeReview, I have to comment on the horror of your hungarian notation. I'm fine with your alignment though, assuming you're using elastic tabstops and not spaces. \$\endgroup\$
    – Magus
    May 2 '14 at 16:39
  • \$\begingroup\$ @Magus AFAIK, F# doesn't have macros. \$\endgroup\$
    – svick
    May 3 '14 at 16:22
  • \$\begingroup\$ Ah, I overestimated the team's cleverness, then. \$\endgroup\$
    – Magus
    May 5 '14 at 14:12
2
\$\begingroup\$

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<Sector>(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<Sector>(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<Sector>(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.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ I think I'd also rename ModelClass, but to something slightly different: YourProgramModel, DataModel or something similar. Base can sometimes be a nice suffix to avoid confusion, but it only conveys how it was implemented rather than what it's for, and Model is a very generic word which can mean different things in different contexts. \$\endgroup\$
    – Magus
    May 2 '14 at 19:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.