当我尝试使用带有以下语句的反射设置值时,我遇到了{{1>}消息 Property set method not found。:
System.ArgumentException
This question on SO表示由于继承而出现问题,但是我无法弄清楚如何使用当前代码解决问题。
我基本上要做的是使用 NHibernate 在审核实体上设置创建日期。为此,我得到了以下设置(警告,代码墙!):
propertyInfo.SetValue(instance, newValue,
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.SetProperty | BindingFlags.Instance, null,
null, null);
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;
}
我可以做出哪些改变来克服这个问题?
答案 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);
}
将起作用