How to set properties on a generic entity?

c# entity-framework

Question

I'd like to check if an entity has 3 properties. CreatedDate, ModifiedDate, and ModifiedBy.

Right now I am just hardcoding the ones that I know have them in the SaveChanges() method of my Object Context.

For instance:

bool newEntity = (entry.State == EntityState.Added);

if (type == typeof(Foo))
{
  var r = entry.Entity as Foo;
  if (r != null)
  {
    if (newEntity) 
      r.CreatedDate = DateTime.Now;
    r.ModifiedDate = DateTime.Now;
    r.ModifiedBy = HttpContext.Current.User.Identity.Name;
  }
}

I know it's possible to check if an object has a certain method using code similar to this:

public static bool HasMethod(this object objectToCheck, string methodName)
{
    var type = objectToCheck.GetType();
    return type.GetMethod(methodName) != null;
} 

But how would I get at those properties without directly casting the entity?

How can I do something like:

if (HasMethod(entry.Entity))
      entry.Entity.ModifiedDate = DateTime.Now;

I am using ASP.Net MVC 4.

1
10
6/6/2013 1:01:29 PM

Accepted Answer

You can use below method. It will set the property if exists. Using GetType at each call may cause some overhead, it needs optimization.

    private bool TrySetProperty(object obj, string property, object value) {
        var prop = obj.GetType().GetProperty(property, BindingFlags.Public | BindingFlags.Instance);
        if(prop != null && prop.CanWrite) {
            prop.SetValue(obj, value, null);
            return true;
        }
        return false;
    }

Usage

 TrySetProperty(entry.Entity, "ModifiedDate", DateTime.Now);
19
3/5/2020 11:00:51 PM

Popular Answer

You can either use reflection -- which has been mentioned by several people already -- or you can create an interface. If you are using auto-generated entities, they are defined with the partial keyword, so you can create another class file in the same project, and give it the same namespace and class definition, and you can have that implement your interface. Then in the code you posted above, you check to see if the object implements your interface, if so, cast to it, then set the values.

The advantage of the interface is that you aren't using reflection (which can be an expensive operation), and also, any future entities you create will work automatically just by implementing your interface.

In cases where your entity properties don't exactly match your interface, you can explicitly implement the interface, that will handle any naming irregularities.

Example: Let's say you've defined an interface, IContainAuditProperties, and you have all your applicable entities implement that interface, you could do the following inside a block where you are looping over all your new/altered entities:

var entity = entry.Entity as IContainAuditProperties;
if(entity != null)
{
  entity.CreatedDate = DateTime.Now;
  entity.ModifiedDate = DateTime.Now;
  //etc.
}


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow