C# .NET反射集私有属性
如果您有这样定义的属性:C# .NET反射集私有属性,c#,.net,reflection,C#,.net,Reflection,如果您有这样定义的属性: private DateTime modifiedOn; public DateTime ModifiedOn { get { return modifiedOn; } } 如何通过反射将其设置为特定值 我两个都试过了: dto.GetType().GetProperty("ModifiedOn").SetValue(dto, modifiedOn, null); 及 但是没有成功。抱歉,如果这是一个愚蠢的问题,但这是我第一次在C#.NET中使用反射。该没有
private DateTime modifiedOn;
public DateTime ModifiedOn
{
get { return modifiedOn; }
}
如何通过反射将其设置为特定值
我两个都试过了:
dto.GetType().GetProperty("ModifiedOn").SetValue(dto, modifiedOn, null);
及
但是没有成功。抱歉,如果这是一个愚蠢的问题,但这是我第一次在C#.NET中使用反射。该没有设置器;您需要:
public DateTime ModifiedOn
{
get { return modifiedOn; }
private set {modifiedOn = value;}
}
(您可能必须使用BindingFlags
——我稍后再试)
如果没有setter,您将不得不依赖于模式/字段名(这很脆弱),或者解析IL(非常困难)
以下工作很好:
using System;
class Test {
private DateTime modifiedOn;
public DateTime ModifiedOn {
get { return modifiedOn; }
private set { modifiedOn = value; }
}
}
static class Program {
static void Main() {
Test p = new Test();
typeof(Test).GetProperty("ModifiedOn").SetValue(
p, DateTime.Today, null);
Console.WriteLine(p.ModifiedOn);
}
}
它还适用于自动实现的属性:
public DateTime ModifiedOn { get; private set; }
(如果依赖字段名会严重中断)如果属性没有setter,则无法对其调用SetValue。可以尝试设置支持字段,而不是属性;您应该使用
GetField()
而不是GetProperty()
您需要设置字段,因为您没有设置属性来设置属性。
对于非公共对象,还需要BindingFlags.NonPublic
dto.GetType().
GetField("modifiedOn",
BindingFlags.NonPublic|BindingFlags.SetField|BindingFlags.Instance).
SetValue(dto, valueToSet);
如果您具有具有setter的私有属性,则可以使用此扩展方法设置值:
using System.Reflection;
public static class ObjectExtensions
{
public static void SetPrivateValue<T>(this T obj, string propertyName, object value)
{
var type = typeof(T);
type.GetTypeInfo().GetDeclaredProperty(propertyName).SetValue(obj, value, null);
}
}
使用系统反射;
公共静态类对象扩展
{
公共静态void SetPrivateValue(此T对象,字符串propertyName,对象值)
{
var类型=类型(T);
type.GetTypeInfo().GetDeclaredProperty(propertyName).SetValue(obj,value,null);
}
}
考虑到set
可能存在也可能不存在,一种方法是使用特定的访问器,这可能是最正确的方法
var myc=new MyClass();
var pi=typeof(MyClass).GetProperty(“Prop1”,BindingFlags.NonPublic | BindingFlags.Instance);
if(pi.SetMethod!=null)//检查是否有“set”访问器
调用(myc,新对象[]{someValue});
其他的
{
//不做任何事或
抛出新异常(“试图设置只读属性”+pi.Name);
}
Cool,没想到能在setter面前拥有private。我想我得检查一下那些标志。Thx。如果整个属性都是私有的,您似乎只需要BindingFlags
。仍然不起作用,所以我想我必须使用这些BindingFlags?定义“不起作用”-会发生什么?我发布的示例效果很好。。。另外:您正在使用CF吗?银灯?还是普通的.NET?(这很重要…)有一刻,你可能忘记了什么。虽然这会起作用,但访问字段通常是一种更脆弱的反射形式。例如,当有人发现C#3.0并使其成为C#3.0时会发生什么:public DateTime ModifiedOn{get;private set;}
?如果您确实想设置backing字段,为了最大限度地减少中断的机会,我将尝试找到以下三种可能性中的每一种:(1)相同的名称,I大小写。(2) 下划线+相同名称,忽略大小写。(3) 自动属性的备份字段的默认命名方案(在SO上很容易找到)。请注意,GetField()具有允许IgnoreCase的重载。
using System.Reflection;
public static class ObjectExtensions
{
public static void SetPrivateValue<T>(this T obj, string propertyName, object value)
{
var type = typeof(T);
type.GetTypeInfo().GetDeclaredProperty(propertyName).SetValue(obj, value, null);
}
}