繁体   English   中英

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

[英]Property set method not found (expression, audited entity)

我正在遇到System.ArgumentException消息未找到属性设置方法。 当我尝试通过以下语句使用反射来设置值时:

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

SO上的这个问题表明问题是由于继承而引起的,但是我无法弄清楚如何用当前代码解决它。

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

IEntity

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

EntityBase

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

IHasCreationTime

public interface IHasCreationTime {
    DateTime CreationTime { get; }
}

ICreationAudited

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

TestEntity

public class TestEntity : EntityBase<int>, ICreationAudited {

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

} 

NHibernateAuditInterceptor

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;
    }

}

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;

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

}

GetMember扩展

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

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

RemoveUnary扩展

private static MemberExpression RemoveUnary(Expression toUnwrap)
{
    var unwrap = toUnwrap as UnaryExpression;
    if (unwrap != null)
    {
        return unwrap.Operand as MemberExpression;
    }

    return toUnwrap as MemberExpression;
}

我可以做些什么改变来克服这个问题?

您的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);
    }

那可行

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM