답변:
예, 다음을 사용할 수 있습니다 Type.InvokeMember()
.
using System.Reflection;
MyObject obj = new MyObject();
obj.GetType().InvokeMember("Name",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty,
Type.DefaultBinder, obj, "Value");
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);
}
obj.GetType().GetProperty("Name")?.GetSetMethod()?.Invoke(...)
CanWrite=False
유형에 대한 가치를 설정하는 것이 불가능 합니까?
당신은 또한 할 수 있습니다 :
Type type = target.GetType();
PropertyInfo prop = type.GetProperty("propertyName");
prop.SetValue (target, propertyValue, null);
여기서 target은 속성이 설정 될 객체입니다.
반사, 기본적으로, 즉
myObject.GetType().GetProperty(property).SetValue(myObject, "Bob", null);
또는 편의성과 성능 측면에서 모두 도움이되는 라이브러리가 있습니다. 예를 들어 FastMember :
var wrapped = ObjectAccessor.Create(obj);
wrapped[property] = "Bob";
(또한 필드 대 속성인지 사전에 알 필요가 없다는 이점이 있습니다)
또는 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 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);
}
}
또는
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);
}
}
속성 이름을 사용하여 다른 개체에서 개체의 속성을 대량 할당하려는 경우이 기능을 사용해 볼 수 있습니다.
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;
}
}
}
}
방금 첫 번째 수준의 속성뿐만 아니라 주어진 객체에 중첩 속성을 설정할 수있는 Nuget 패키지를 방금 게시했습니다.
여기 패키지가 있습니다
루트에서 경로로 객체의 속성 값을 설정합니다.
개체는 복잡한 개체 일 수 있으며 속성은 다중 수준의 딥 중첩 속성이거나 루트 바로 아래에있는 속성 일 수 있습니다. ObjectWriter
속성 경로 매개 변수를 사용하여 속성을 찾고 값을 업데이트합니다. 속성 경로는 루트에서 우리가 설정하려는 끝 노드 속성까지 방문한 속성의 추가 된 이름으로 구분자 문자열 매개 변수로 구분됩니다.
용법:
오브젝트 루트 바로 아래에 특성을 설정하려면 다음을 수행하십시오.
즉. LineItem
클래스에는라는 int 속성이 있습니다ItemId
LineItem lineItem = new LineItem();
ObjectWriter.Set(lineItem, "ItemId", 13, delimiter: null);
객체 루트 아래에 여러 수준의 중첩 속성을 설정하려면 다음을 수행하십시오.
즉. Invite
class에는이라는 속성 State
이 있으며,이 속성에는 Invite
(초대 유형)이라는 속성 Recipient
이 있으며, 속성에는 속성이 Id
있습니다.
일을 더욱 복잡하게하기 위해이 State
속성은 참조 유형이 아닙니다 struct
.
개체 트리의 맨 아래에 Id 속성 (문자열 값 "Outlook")을 한 줄로 설정하는 방법은 다음과 같습니다.
Invite invite = new Invite();
ObjectWriter.Set(invite, "State_Invite_Recipient_Id", "outlook", delimiter: "_");
MarcGravell의 제안에 따라 다음과 같은 정적 메소드를 구성했습니다.이 메소드는 일반적으로 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);
}
}
}
var val = Convert.ChangeType(propValue, propInfo.PropertyType);
source : devx.com/vb2themax/Tip/19599