Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.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# 使用反射设置对象属性_C#_.net_Reflection_Properties - Fatal编程技术网

C# 使用反射设置对象属性

C# 使用反射设置对象属性,c#,.net,reflection,properties,C#,.net,Reflection,Properties,在C#中有没有一种方法可以使用反射来设置对象属性 例: 我想设置带有反射的obj.Name。比如: Reflection.SetProperty(obj, "Name") = "Value"; 有办法吗?是的,您可以使用Type.InvokeMember(): 如果obj没有名为Name的属性,或者无法设置该属性,则会引发异常 另一种方法是获取属性的元数据,然后设置它。这将允许您检查属性是否存在,并验证是否可以设置该属性: using System.Reflection; MyObject o

在C#中有没有一种方法可以使用反射来设置对象属性

例:

我想设置带有反射的
obj.Name
。比如:

Reflection.SetProperty(obj, "Name") = "Value";

有办法吗?

是的,您可以使用
Type.InvokeMember()

如果
obj
没有名为
Name
的属性,或者无法设置该属性,则会引发异常

另一种方法是获取属性的元数据,然后设置它。这将允许您检查属性是否存在,并验证是否可以设置该属性:

using System.Reflection;
MyObject obj = new MyObject();
PropertyInfo prop = obj.GetType().GetProperty("Name", BindingFlags.Public | BindingFlags.Instance);
if(null != prop && prop.CanWrite)
{
    prop.SetValue(obj, "Value", null);
}
您还可以执行以下操作:

Type type = target.GetType();

PropertyInfo prop = type.GetProperty("propertyName");

prop.SetValue (target, propertyValue, null);

其中target是将设置其属性的对象。

您也可以使用类似的方式访问字段:

var obj=new MyObject();
FieldInfo fi = obj.GetType().
  GetField("Name", BindingFlags.NonPublic | BindingFlags.Instance);
fi.SetValue(obj,value)

有了反射,一切都可以成为一本打开的书:)在我的示例中,我们绑定到一个私有实例级字段

反射,基本上,即

myObject.GetType().GetProperty(property).SetValue(myObject, "Bob", null);
或者有图书馆在方便性和性能方面提供帮助;例如:


(还有一个优点是不需要事先知道它是字段还是属性)

是,使用
系统。反射

using System.Reflection;

...

    string prop = "name";
    PropertyInfo pi = myObject.GetType().GetProperty(prop);
    pi.SetValue(myObject, "Bob", null);

或者,您可以将Marc的一行代码封装在自己的扩展类中:

public static class PropertyExtension{       

   public static void SetPropertyValue(this object obj, string propName, object value)
    {
        obj.GetType().GetProperty(propName).SetValue(obj, value, null);
    }
}
这样称呼它:

myObject.SetPropertyValue("myProperty", "myValue");
为了更好地度量,让我们添加一个方法来获取属性值:

public static object GetPropertyValue(this object obj, string propName)
{
        return obj.GetType().GetProperty(propName).GetValue (obj, null);
}

如果要使用特性名称从另一个对象批量指定对象的特性,可以尝试此方法:

public static void Assign(this object destination, object source)
    {
        if (destination is IEnumerable && source is IEnumerable)
        {
            var dest_enumerator = (destination as IEnumerable).GetEnumerator();
            var src_enumerator = (source as IEnumerable).GetEnumerator();
            while (dest_enumerator.MoveNext() && src_enumerator.MoveNext())
                dest_enumerator.Current.Assign(src_enumerator.Current);
        }
        else
        {
            var destProperties = destination.GetType().GetProperties();
            foreach (var sourceProperty in source.GetType().GetProperties())
            {
                foreach (var destProperty in destProperties)
                {
                    if (destProperty.Name == sourceProperty.Name && destProperty.PropertyType.IsAssignableFrom(sourceProperty.PropertyType))
                    {
                        destProperty.SetValue(destination,     sourceProperty.GetValue(source, new object[] { }), new object[] { });
                        break;
            }
        }
    }
}

使用以下内容:

public static class PropertyExtension{       

   public static void SetPropertyValue(this object p_object, string p_propertyName, object value)
   {
    PropertyInfo property = p_object.GetType().GetProperty(p_propertyName);
    property.SetValue(p_object, Convert.ChangeType(value, property.PropertyType), null);
   }
}


我刚刚发布了一个Nuget包,它不仅允许设置第一级属性,还允许在给定对象的任何深度设置嵌套属性

这是

通过对象从根开始的路径设置对象特性的值

对象可以是复杂对象,属性可以是多级深嵌套属性,也可以是根目录下的直接属性
ObjectWriter
将使用property path参数查找属性并更新其值。Property path是从根访问的属性的附加名称,附加到要设置的结束节点属性,由delimiter string参数分隔

用法:

要直接在对象根目录下设置属性,请执行以下操作:

例如,
LineItem
类有一个名为
ItemId

LineItem lineItem = new LineItem();

ObjectWriter.Set(lineItem, "ItemId", 13, delimiter: null);
要在对象根下设置多个嵌套属性级别,请执行以下操作:

例如,
Invite
类有一个名为
State
的属性,该属性有一个名为
Invite
(邀请类型)的属性,该属性有一个名为
Recipient
的属性,该属性有一个名为
Id

更复杂的是,
State
属性不是引用类型,而是一个
struct

下面是如何在一行中设置对象树底部的Id属性(字符串值为“outlook”)

Invite invite = new Invite();

ObjectWriter.Set(invite, "State_Invite_Recipient_Id", "outlook", delimiter: "_");

根据MarcGravel的建议,我构建了以下静态方法。该方法一般使用FastMember分配源对象到目标的所有匹配属性

 public static void DynamicPropertySet(object source, object target)
    {
        //SOURCE
        var src_accessor = TypeAccessor.Create(source.GetType());
        if (src_accessor == null)
        {
            throw new ApplicationException("Could not create accessor!");
        }
        var src_members = src_accessor.GetMembers();
        if (src_members == null)
        {
            throw new ApplicationException("Could not fetch members!");
        }
        var src_class_members = src_members.Where(x => x.Type.IsClass && !x.Type.IsPrimitive);
        var src_class_propNames = src_class_members.Select(x => x.Name);
        var src_propNames = src_members.Except(src_class_members).Select(x => x.Name);

        //TARGET
        var trg_accessor = TypeAccessor.Create(target.GetType());
        if (trg_accessor == null)
        {
            throw new ApplicationException("Could not create accessor!");
        }
        var trg_members = trg_accessor.GetMembers();
        if (trg_members == null)
        {
            throw new ApplicationException("Could not create accessor!");
        }
        var trg_class_members = trg_members.Where(x => x.Type.IsClass && !x.Type.IsPrimitive);
        var trg_class_propNames = trg_class_members.Select(x => x.Name);
        var trg_propNames = trg_members.Except(trg_class_members).Select(x => x.Name);



        var class_propNames = trg_class_propNames.Intersect(src_class_propNames);
        var propNames = trg_propNames.Intersect(src_propNames);

        foreach (var propName in propNames)
        {
            trg_accessor[target, propName] = src_accessor[source, propName];
        }
        foreach (var member in class_propNames)
        {
            var src = src_accessor[source, member];
            var trg = trg_accessor[target, member];
            if (src != null && trg != null)
            {
                DynamicPropertySet(src, trg);
            }
        }
    }

我今天也做了同样的事情。上述方法非常有效,显然在尝试使用道具之前应该对道具进行空检查。@AntonyScott我想你应该想知道你是否调用了错误的属性,所以“无声失败”似乎是一个糟糕的过程。@j.I.h.我明白你的观点,但这取决于实际情况。哇,从合并中有点困惑,但我又找到了你的答案!谢谢,你应该得到一个“接受”,但由于我的线程被合并:(再次感谢!@MarcGravel,我在看FastMember,它非常有趣。有没有入门/教程让我们这些凡人使用你这个伟大的库?我如何通过FastMember获得属性类型?@Jahan accessor=>GetMembers=>Member=>Typegreat answer!oneliner的优点是速度非常快呃,要理解,因为没有用户命名的变量,这对你来说可能没有任何意义。如果你不处理所有的字符串,你可能想先转换数据:
var val=convert.ChangeType(propValue,propInfo.PropertyType);
source:或者,你可以使用
obj.GetType().GetProperty(“Name”)?.GetSetMethod()?.Invoke(…)
无法为
CanWrite=False
类型设置值,对吗?您好,欢迎来到Stack Overflow。请正确设置代码格式,而不仅仅是将其转储到您的帖子中,这将帮助其他人理解您的答案。您获取属性类型然后将其转换的部分对我来说非常有用。它非常有用。谢谢
public static class PropertyExtension{       

   public static void SetPropertyValue(this object p_object, string p_propertyName, object value)
   {
    PropertyInfo property = p_object.GetType().GetProperty(p_propertyName);
    Type t = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType;
    object safeValue = (value == null) ? null : Convert.ChangeType(value, t);

    property.SetValue(p_object, safeValue, null);
   }
}
LineItem lineItem = new LineItem();

ObjectWriter.Set(lineItem, "ItemId", 13, delimiter: null);
Invite invite = new Invite();

ObjectWriter.Set(invite, "State_Invite_Recipient_Id", "outlook", delimiter: "_");
 public static void DynamicPropertySet(object source, object target)
    {
        //SOURCE
        var src_accessor = TypeAccessor.Create(source.GetType());
        if (src_accessor == null)
        {
            throw new ApplicationException("Could not create accessor!");
        }
        var src_members = src_accessor.GetMembers();
        if (src_members == null)
        {
            throw new ApplicationException("Could not fetch members!");
        }
        var src_class_members = src_members.Where(x => x.Type.IsClass && !x.Type.IsPrimitive);
        var src_class_propNames = src_class_members.Select(x => x.Name);
        var src_propNames = src_members.Except(src_class_members).Select(x => x.Name);

        //TARGET
        var trg_accessor = TypeAccessor.Create(target.GetType());
        if (trg_accessor == null)
        {
            throw new ApplicationException("Could not create accessor!");
        }
        var trg_members = trg_accessor.GetMembers();
        if (trg_members == null)
        {
            throw new ApplicationException("Could not create accessor!");
        }
        var trg_class_members = trg_members.Where(x => x.Type.IsClass && !x.Type.IsPrimitive);
        var trg_class_propNames = trg_class_members.Select(x => x.Name);
        var trg_propNames = trg_members.Except(trg_class_members).Select(x => x.Name);



        var class_propNames = trg_class_propNames.Intersect(src_class_propNames);
        var propNames = trg_propNames.Intersect(src_propNames);

        foreach (var propName in propNames)
        {
            trg_accessor[target, propName] = src_accessor[source, propName];
        }
        foreach (var member in class_propNames)
        {
            var src = src_accessor[source, member];
            var trg = trg_accessor[target, member];
            if (src != null && trg != null)
            {
                DynamicPropertySet(src, trg);
            }
        }
    }