0

I'm having a situation where type of each business object in my application has to be saved to some table in the database. I would need to represent each type by some enum or sorts.

There exists a basic framework in another dll which is independent of my model, and should be. My model classes have to inherit a base class/interface from the external framework first of all. The problem is I cant have the enum that represents my business objects in the external dll since that should be independent of any model. For instance,

Base class in external dll:

namespace external
{
    public enum EnumThatDenotesPoco { Vehicle, Animal, Foo }

    public abstract class Framework
    {
        public abstract EnumThatDenotesPoco RecordType { get; }
    }
}

and my project:

namespace ourApplication
{
    public class Vehicle : Framework
    {
        public override EnumThatDenotesPoco RecordType { get { return  EnumThatDenotesPoco.Vehicle; } }
    }
}

wont work since Vehicle, Animal, Foo are in my application project. What would be a better design in this case?

I have two ways to go about it, but not sure if that's the right approach.

1.

namespace external
{
    public abstract class Framework
    {
        public abstract Enum RecordType { get; } //base class of all enums
    }
}

namespace ourApplication
{
    public enum EnumThatDenotesPoco { Vehicle, Animal, Foo }

    public class Vehicle : Framework
    {
        public override Enum RecordType { get { return  EnumThatDenotesPoco.Vehicle; } }
    }
}

This works. vehicle.RecordType. rightly yields 0.

2.

namespace external
{
    public class EntityBase // an empty enum class
    {

    }

    public abstract class Framework
    {
        public abstract EntityBase RecordType { get; } 
    }
}

namespace ourApplication
{
    public sealed class Entity : EntityBase
    {
        public static readonly Entity Vehicle = 1;
        public static readonly Entity Animal = 2;
        public static readonly Entity Foo = 3; //etc

        int value;
        public static implicit operator Entity(int x)
        {
            return new Entity { value = x };
        }

        public override string ToString()
        {
            return value.ToString();
        }
    }

    public class Vehicle : Framework
    {
        public override EntityBase RecordType { get { return  Entity.Vehicle; } }
    }
}

Both works.

nawfal
  • 70,104
  • 56
  • 326
  • 368

1 Answers1

1

Contemplating T4 template I found it more complex than needed. I went with my second approach with some modifications.

Problem with Enum approach:

  1. I can save System.Enum directly (Convert.ToInt32(System.Enum), System.Enum.ToString() etc can give the actual underlying value) to db but I won't be able to retrieve it cleanly from db back as System.Enum.

  2. System.Enum is totally generic and can be confusing as it reveals nothing.

I went with the second approach but with minor modifications:

namespace external
{
    public abstract class Framework
    {
        public abstract Entity RecordType { get; } 
    }



    public sealed class Entity
    {
        int value;

        Entity()
        {

        }

        public static implicit operator Entity(int i)
        {
            return new Entity { value = i };
        }

        public bool Equals(Entity other)
        {
            if (ReferenceEquals(this, other))
                return true;

            if (ReferenceEquals(null, other))
                return false;

            return value == other.value;
        }

        public override bool Equals(object obj)
        {
            return Equals(obj as Entity);
        }

        public static bool operator ==(Entity lhs, Entity rhs)
        {
            if (ReferenceEquals(lhs, null))
                return ReferenceEquals(rhs, null);

            return lhs.Equals(rhs);
        }

        public static bool operator !=(Entity lhs, Entity rhs)
        {
            return !(lhs == rhs);
        }

        public override int GetHashCode()
        {
            return value;
        }

        public override string ToString()
        {
            return value.ToString();
        }
    }
}

I made the base enum class (Entity) non empty by giving all the logic there. So now I don't require the validation code to be written in referenced projects. I can write enum values somewhere in my main assembly:

namespace ourApplication
{
    public static class Global
    {
        public static readonly Entity Vehicle = 1;
        public static readonly Entity Animal = 2;
        public static readonly Entity Foo = 3; //etc
    }

    public class Vehicle : Framework
    {
        public override Entity RecordType { get { return  Global.Vehicle; } }
    }
}

Now saving and retrieving is a breeze:

//insert as just vehicle.RecordType

//select as (Entity)reader.GetInt32(index)
nawfal
  • 70,104
  • 56
  • 326
  • 368