如何在通用实体上设置属性?

Smi*_*ith 10 c# entity-framework

我想检查一个实体是否有3个属性.CreatedDate,ModifiedDate和ModifiedBy.

现在我只是在我的对象上下文的SaveChanges()方法中硬编码我知道的那些.

例如:

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;
  }
}
Run Code Online (Sandbox Code Playgroud)

我知道可以使用与此类似的代码检查对象是否具有某种方法:

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

但是,如果不直接投射实体,我将如何获得这些属性?

我该怎么做:

if (HasMethod(entry.Entity))
      entry.Entity.ModifiedDate = DateTime.Now;
Run Code Online (Sandbox Code Playgroud)

我正在使用ASP.Net MVC 4.

Meh*_*taş 19

您可以使用以下方法.如果存在,它将设置属性.GetType在每次调用时使用可能会导致一些开销,需要优化.

    private void 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);
    }
Run Code Online (Sandbox Code Playgroud)

用法

 TrySetProperty(entry.Entity, "ModifiedDate", DateTime.Now);
Run Code Online (Sandbox Code Playgroud)


Bri*_*all 6

你可以使用反射 - 已经被几个人提到过了 - 或者你可以创建一个界面.如果您使用自动生成的实体,则使用partial关键字定义它们,因此您可以在同一个项目中创建另一个类文件,并为其指定相同的命名空间和类定义,并且可以实现您的接口.然后在上面发布的代码中,检查对象是否实现了您的界面,如果是,则转换为它,然后设置值.

界面的优点是您不使用反射(这可能是一项昂贵的操作),而且,您创建的任何未来实体都将通过实现您的界面自动运行.

如果您的实体属性与您的接口不完全匹配,您可以显式实现该接口,该接口将处理任何命名不规则.

示例:假设您已经定义了一个接口,IContainAuditProperties并且您拥有所有适用的实体实现该接口,您可以在一个块中执行以下操作,在该块中循环所有新的/更改的实体:

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

  • 我同意布莱恩的观点。接口绝对是解决问题的方法。 (2认同)