[英]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在受审核实体上设置创建日期 。 为此,我进行了以下设置( 警告,代码墙! ):
public interface IEntity<TKey> : IEquatable<IEntity<TKey>>
{
TKey Id { get; }
bool IsTransient { get; }
TKey GetDefaultId();
}
public abstract class EntityBase<TKey> : IEntity<TKey>
{
// omitted for brevity
}
public interface IHasCreationTime {
DateTime CreationTime { get; }
}
public interface ICreationAudited : IHasCreationTime {
string CreatorId { get; }
}
public class TestEntity : EntityBase<int>, ICreationAudited {
public string Name { get; set; }
public string CreatorId { get; set; }
public DateTime CreationTime { get; set; }
}
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;
}
}
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..
}
public static MemberInfo GetMember<T, TProperty>(this Expression<Func<T, TProperty>> expression)
{
var memberExp = RemoveUnary(expression.Body);
return memberExp == null ? null : memberExp.Member;
}
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.