Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# .NET反射集私有属性_C#_.net_Reflection - Fatal编程技术网

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