1

说我有以下方法:

private static void SetLastModifiedTimeUser<TEntity>(TEntity entity) where TEntity : class
{
    PropertyInfo propertyInfo;

    propertyInfo = entity.GetType().GetProperty("LastModifiedUser");
    if (propertyInfo != null)
        propertyInfo.SetValue(entity, IdentityHelper.UserName, null);
}

如您所见,该方法接受泛型类型。传递给此方法的每个类都将包含一个名为“LastModifiedUser”的属性。有没有一种方法可以在不使用反射的情况下访问此属性?我不认为有,但我想我会问。

4

4 回答 4

4

是的,如果您的所有实体都具有LastModifiedUser属性,那么您可以使所有实体都从基类继承,或者实现一些接口,例如

public interface IModifyable
{
    string LastModifiedUser { get; set; }
}

然后只需添加此约束(或使您的方法非泛型,接受IModifyable

where TEntity : class, IModifyable

您的代码将如下所示:

private static void SetLastModifiedTimeUser<TEntity>(TEntity entity) 
   where TEntity : class, IModifyable
{
   entity.LastModifiedUser = IdentityHelper.UserName;
}
于 2012-12-03T20:25:30.187 回答
3

让您的类从定义LastModifiedUser属性的接口继承。

public interface ILastModifiedUser
{
    public string LastModifiedUser { get; set; }
}

将您的方法声明更改为

private static void SetLastModifiedTimeUser(ILastModifiedUser entity)
于 2012-12-03T20:26:06.643 回答
1

如果你不能修改所有的类来实现一个通用的接口,你可以使用dynamic

private static void SetLastModifiedTimeUser<TEntity>(TEntity entity) where TEntity : class
{
    dynamic d = entity;
    d.LastModifiedUser = IdentityHelper.UserName;
}

否则它就像Robert Harvey所示的那样简单。

于 2012-12-03T20:27:25.237 回答
1

如果您无法向对象添加接口,请考虑这种方法。

第一次遇到每个类型(TEntity)时,它会查找属性并获取属性的 SetMethod。然后,在每次使用时,它都会创建调用该方法。

var one = new EntityOne();
LastModifiedTimeUserSetter.Set(one);
Console.WriteLine(one.LastModifiedUser);

public static class LastModifiedTimeUserSetter
{
  public static void Set<TEntity>(TEntity entity)
  {
     var method = Properties.GetOrAdd(typeof (TEntity), GetSetMethod);
     var action = (Action<string>) Delegate.CreateDelegate(typeof (Action<string>), entity, method);
     action(IdentityHelper.UserName);
  }
  static MethodInfo GetSetMethod(Type type)
  {
     var prop = type.GetProperty("LastModifiedUser");
     if (prop == null)
        return null;
     return prop.GetSetMethod();
  }

  static readonly ConcurrentDictionary<Type, MethodInfo> Properties = new ConcurrentDictionary<Type, MethodInfo>();
}

走得更远

有一种方法可以通过使用System.Reflection.Emit.MethodBuilder来进一步提高性能。并构建一个采用 Entity 并设置属性的方法。

public static class LastModifiedTimeUserSetter
{
  public static void Set<TEntity>(TEntity entity)
  {
     var action = (Action<TEntity>) Properties.GetOrAdd(typeof(TEntity), CreateDynamicSetMethodDelegate);
     if(action != null)
        action(entity);
  }

  static Delegate CreateDynamicSetMethodDelegate(Type type)
  {
     return CreateDynamicSetMethod(type).CreateDelegate(GetActionType(type));
  }

  static DynamicMethod CreateDynamicSetMethod(Type typeWithProperty)
  {
     var methodBuilder = new DynamicMethod(
        "Dynamic_" + typeWithProperty.FullName + "_SetLastModifiedUser",
        typeof (void),
        new[] {typeWithProperty});
     EmitSimpleAssignmentMethod(methodBuilder,
                                GetIdentityHelperUserNameGetMethod(),
                                GetPropertySetMethod(typeWithProperty));
     return methodBuilder;
  }

  static MethodInfo GetIdentityHelperUserNameGetMethod()
  {
     return typeof(IdentityHelper).GetProperty("UserName").GetGetMethod();
  }

  static MethodInfo GetPropertySetMethod(Type type)
  {
     var prop = type.GetProperty("LastModifiedUser");
     if (prop == null)
        return null;
     return prop.GetSetMethod();
  }

  static void EmitSimpleAssignmentMethod(DynamicMethod methodBuilder, MethodInfo getMethod, MethodInfo setMethod)
  {
     var il = methodBuilder.GetILGenerator();
     il.Emit(OpCodes.Ldarg_0);
     il.EmitCall(OpCodes.Call, getMethod, null);
     il.EmitCall(OpCodes.Call, setMethod, null);
     il.Emit(OpCodes.Ret);
  }

  static Type GetActionType(Type type)
  {
     return typeof (Action<string>).GetGenericTypeDefinition().MakeGenericType(type);
  }

  static readonly ConcurrentDictionary<Type, Delegate> Properties = new ConcurrentDictionary<Type, Delegate>();
}

请参阅MSDN 杂志上有关 XBOX Live 的文章

于 2012-12-03T21:27:07.887 回答