Use extension methods to let your enums hold the logic.

I often stumble upon code checking values on enumerations to determine the state of some object or rule. At best, this code is extracted and put in a helper or utils class of some sort. Don’t! Use extension methods instead. It let’s you provide a name for the condition (rule) that you are checking, and it put’s it together with the enumeration.

Example
Lets say I have an enumeration with storage providers. Each provider might be able to store data virtually, hence I need the possibility of determining if it’s capable of this.

[Serializable]
public enum StorageProviders
{
    LuceneIo = 0,
    LuceneVirtual = 1
}

public static class StorageProvidersExtensions
{
    public static bool IsVirtual(this StorageProviders provider)
    {
        return provider == StorageProviders.LuceneVirtual;
    }
}

I can now act on the enumeration value it self.

...connectionInfo.ProviderType.IsVirtual()...

//Daniel

2 thoughts on “Use extension methods to let your enums hold the logic.

  1. I was looking at your code first EF4. Ran into a lot of trouble mapping the entities correctly, for some reason the complete object graph is not being persisted when doing update below are the entities and their mapping
    which are an extension of your sample
    public interface IEfEntity
    {
    int Id { get; set; }
    byte[] Version { get; set; }
    }

    public abstract class EfEntity : IEfEntity
    {
    public virtual int Id { get; set; }
    public virtual byte[] Version { get; set; }
    }

    [Serializable]
    public class EfCustomer
    : EfEntity
    {
    public string Firstname { get; set; }
    public string Lastname { get; set; }
    public ICollection Addresses { get; set; }
    public ICollection CustomerPhones { get; set; }
    public string Name
    {
    get { return string.Format("{0} {1}", Firstname, Lastname).Trim(); }
    }

    public EfCustomer()
    {
    Addresses = new List();
    CustomerPhones = new List();
    }
    }

    public class EfAddress : EfEntity
    {
    public virtual string Address1 { get; set; }
    public virtual string Address2 { get; set; }
    public virtual string City { get; set; }
    public virtual string ZipCode { get; set; }
    public virtual string State { get; set; }
    public virtual EfCustomer Customer { get; set; }
    public virtual int Customer_Id { get; set; }
    }

    public class EfCustomerPhone : EfEntity
    {
    public virtual bool IsActive { get; set; }
    public virtual EfCustomer Customer { get; set; }
    public ICollection Phones { get; set; }
    public virtual int Customer_Id { get; set; }

    public virtual void PhoneAdd(EfPhone efPhone)
    {
    Phones.Add(efPhone);
    }

    public EfCustomerPhone()
    {
    // Phones = new List();
    }

    }

    public class EfPhone : EfEntity
    {
    public virtual string PhoneNumber { get; set; }
    public virtual EfCustomerPhone CustomerPhone { get; set; }
    public virtual int CustomerPhone_Id { get; set; }
    }

    [Serializable]
    public abstract class EntityMapping : EntityConfiguration where T : EfEntity
    {
    protected EntityMapping()
    {
    HasKey(o => o.Id);
    Property(o => o.Id)
    .IsIdentity();
    Property(o => o.Version)
    .IsConcurrencyToken()
    .IsRequired()
    .HasStoreType("timestamp")
    .StoreGeneratedPattern = StoreGeneratedPattern.Computed;
    }
    }

    [Serializable]
    public class CustomerMapping : EntityMapping
    {
    public CustomerMapping()
    {
    Property(o => o.Firstname)
    .HasMaxLength(100)
    .IsUnicode()
    .IsOptional();
    Property(o => o.Lastname)
    .HasMaxLength(100)
    .IsUnicode()
    .IsOptional();
    Relationship(u => u.Addresses).FromProperty(p => p.Customer);
    Relationship(u => u.CustomerPhones).FromProperty(p => p.Customer);
    }
    }

    [Serializable]
    public class AddressMapping : EntityMapping
    {
    public AddressMapping()
    {
    Property(o => o.Address1)
    .HasMaxLength(100)
    .IsUnicode()
    .IsRequired();
    Property(o => o.Address1)
    .HasMaxLength(100)
    .IsUnicode()
    .IsOptional();
    Property(o => o.City)
    .HasMaxLength(24)
    .IsUnicode()
    .IsRequired();
    Property(o => o.State)
    .HasMaxLength(2)
    .IsUnicode()
    .IsRequired();
    Property(o => o.ZipCode)
    .HasMaxLength(12)
    .IsUnicode()
    .IsRequired();
    Relationship(p => p.Customer).IsRequired()
    .IsRequired();
    // Register Inverses mapping
    Relationship(p => p.Customer).FromProperty(u => u.Addresses);
    //FK mapping for reverse lookup
    Relationship(p => p.Customer).FromProperty(b => b.Addresses).HasConstraint((p, b) => p.Customer_Id == b.Id);

    }
    }

    [Serializable]
    public class PhoneMapping : EntityMapping
    {
    public PhoneMapping()
    {
    Property(o => o.PhoneNumber)
    .HasMaxLength(100)
    .IsUnicode()
    .IsRequired();
    Relationship(p => p.CustomerPhone).IsRequired();
    // Register some Inverses
    Relationship(p => p.CustomerPhone).FromProperty(p => p.Phones);
    //MapSingleType(p => new
    // {
    // id = p.Id,
    // phoneNumber = p.PhoneNumber,
    // version = p.Version,
    // customerPhone = EntityMap.Related(c => c.Phones).Id
    // });
    Relationship(p => p.CustomerPhone).FromProperty(b => b.Phones).HasConstraint((p, b) => p.CustomerPhone_Id == b.Id);
    }
    }

    [Serializable]
    public class CustomerPhoneMapping : EntityMapping
    {
    public CustomerPhoneMapping()
    {
    Property(o => o.IsActive);
    Relationship(p => p.Customer).IsRequired()
    .IsRequired();
    // Register Inverses mapping
    Relationship(p => p.Customer).FromProperty(u => u.CustomerPhones);
    Relationship(u => u.Phones).FromProperty(p => p.CustomerPhone).IsRequired();
    //FK mapping for reverse lookup
    Relationship(p => p.Customer).FromProperty(b => b.CustomerPhones).HasConstraint((p, b) => p.Customer_Id == b.Id);
    }
    }

    • Hi,

      It’s because EF doesn’t allow you to “reuse” mappings via inheritance, unless the members are “simple properties”, e.g. strings, ints….

      E.g. CustomerMapping which has relationships will break.

      The EF team knows about this.

      //Daniel

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s