yeomandev
yeomandev

Reputation: 11796

How to access an element of a generic type in C#

I'm working on a reusable database repository method for attaching and saving entities to a database using EntityFramework 4.3.

    private void SaveObject<T>(T entityToSave, DbSet<T> dbSet) where T : class
    {
        if (db.Entry(entityToSave).State == EntityState.Detached)
        {
            if (entityToSave.Id == Guid.Empty) // how do I access the Id property?
                dbSet.Add(entityToSave);
            else
                db.Entry(entityToSave).State = EntityState.Modified;
        }
    } 

The problem that I'm running into is that I need to tell my method which property is the Id so I can check to see if it is set or not. If it is empty, then I know I am creating a brand new record. Otherwise I am modifying an existing record.

How do I tell my method what the Id property is?

Upvotes: 2

Views: 163

Answers (3)

Olivier Jacot-Descombes
Olivier Jacot-Descombes

Reputation: 112279

As others have shown, you can solve the problem by using an interface. Another possibility is to define an accessor delegate

private void SaveObject<T>(T entityToSave, DbSet<T> dbSet, Func<T,Guid> accessId)
{
    ...
    Guid id = accessId(entityToSave);
    ...
}

call with

SaveObject(entityToSave, dbSet, e => e.Id)
SaveObject(otherEntityToSave, dbSet, e => e.UserID)

The advantage over an interface, is that the ids can have different names and, together with a second generic parameter, even different types

private void SaveObject<T,I>(T entityToSave, DbSet<T> dbSet, Func<T,I> accessId)
{
    ...
    I id = accessId(entityToSave);
    ...
}

Upvotes: 1

moribvndvs
moribvndvs

Reputation: 42497

You need an interface or base class that defines the Id property, and use that as your generic constraint. Example:

public interface IEntity
{
    Guid Id { get; }
}

private void SaveObject<T>(T entityToSave, DbSet<T> dbSet) where T : class, IEntity
    {
        if (db.Entry(entityToSave).State == EntityState.Detached)
        {
            if (entityToSave.Id == Guid.Empty) // how do I access the Id property?
                dbSet.Add(entityToSave);
            else
                db.Entry(entityToSave).State = EntityState.Modified;
        }
    } 

Upvotes: 3

SLaks
SLaks

Reputation: 887285

You need to create an interface containing the Id property.

Make all of your entity classes implement this interface and constrain T to implement it. (where T : IHasId)
You will then be able to access all of the members of this interface in your method.

Upvotes: 3

Related Questions