找不到属性集方法(表达式,审计实体)

时间:2014-09-16 08:41:24

标签: c# linq nhibernate reflection expression

当我尝试使用带有以下语句的反射设置值时,我遇到了{{1>}消息 Property set method not found。

System.ArgumentException

This question on SO表示由于继承而出现问题,但是我无法弄清楚如何使用当前代码解决问题。

我基本上要做的是使用 NHibernate 在审核实体上设置创建日期。为此,我得到了以下设置(警告,代码墙!):

IEntity

propertyInfo.SetValue(instance, newValue, 
            BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.SetProperty | BindingFlags.Instance, null, 
            null, null);

EntityBase

public interface IEntity<TKey> : IEquatable<IEntity<TKey>>
{
    TKey Id { get; }
    bool IsTransient { get; }
    TKey GetDefaultId();
}

IHasCreationTime

public abstract class EntityBase<TKey> : IEntity<TKey>
{
    // omitted for brevity
}

ICreationAudited

public interface IHasCreationTime {
    DateTime CreationTime { get; }
}

TestEntity

public interface ICreationAudited : IHasCreationTime {
    string CreatorId { get; }
}

NHibernateAuditInterceptor

public class TestEntity : EntityBase<int>, ICreationAudited {

    public string Name { get; set; }
    public string CreatorId { get; set; }
    public DateTime CreationTime { get; set; }

} 

SetProperty扩展

internal class NHibernateAuditInterceptor : EmptyInterceptor {

    public override bool OnSave(object entity, object id, object[] state, string[] propertyNames, IType[] types)
    {

        var auditable = entity as ICreationAudited;
        if(auditable == null)
            return false;

        auditable.SetProperty(x => x.CreationTime, DateTime.UtcNow);
        return true;
    }

}

GetMember扩展

public static void SetProperty<T, TProperty>(this T instance, Expression<Func<T, TProperty>> selector, TProperty newValue)
    where T: class
{
    var propertyInfo = selector.GetMember() as PropertyInfo;

    propertyInfo.SetValue(instance, newValue, BindingFlags.Public // nonpublic etc..

}

RemoveUnary extension

public static MemberInfo GetMember<T, TProperty>(this Expression<Func<T, TProperty>> expression)
{

    var memberExp = RemoveUnary(expression.Body);
    return memberExp == null ? null : memberExp.Member;
}

我可以做出哪些改变来克服这个问题?

1 个答案:

答案 0 :(得分:1)

由于此表达式,您的SetProperty扩展方法无法编译...

var selector.GetMember() as PropertyInfo;

这不是C#中的有效赋值语句。我会假设你真的想说...

var propertyInfo = selector.GetMember() as PropertyInfo;

如果是这种情况,你可能得到System.ArgumentException的原因是因为你传入的lambda不知道实际类型是什么,它只知道它的契约(接口),但是,您使用的反射方法仅适用于具体类型。要使SetProperty扩展方法起作用,您需要使用实际的具体类,如下所示......

public static void SetProperty<T, TProperty>(this T instance, Expression<Func<T, TProperty>> selector, TProperty newValue)
   where T : class
    {            
        var propertyInfo = selector.GetMember() as PropertyInfo;
        instance.GetType().GetProperty(propertyInfo.Name).SetValue(instance, newValue, null);
    }

将起作用