Yanıtlar:
Evet, şunları kullanabilirsiniz Type.InvokeMember()
:
using System.Reflection;
MyObject obj = new MyObject();
obj.GetType().InvokeMember("Name",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty,
Type.DefaultBinder, obj, "Value");
Bu, obj
çağrılan bir özelliğe sahip değilse Name
veya ayarlanamazsa bir istisna atar .
Başka bir yaklaşım, mülkün meta verilerini almak ve sonra ayarlamaktır. Bu, mülkün varlığını kontrol etmenize ve mülkün ayarlanabildiğinden emin olmanıza olanak tanır:
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
türler için değer belirlemek imkansız , değil mi?
Ayrıca şunları da yapabilirsiniz:
Type type = target.GetType();
PropertyInfo prop = type.GetProperty("propertyName");
prop.SetValue (target, propertyValue, null);
Burada hedef, özelliği ayarlanacak nesnedir.
Yansıma, temelde, yani
myObject.GetType().GetProperty(property).SetValue(myObject, "Bob", null);
veya hem kolaylık hem de performans açısından yardımcı olacak kütüphaneler var; örneğin FastMember ile :
var wrapped = ObjectAccessor.Create(obj);
wrapped[property] = "Bob";
(bu aynı zamanda bir alanın bir mülk olup olmadığını önceden bilmenize gerek olmaması avantajına sahiptir)
Veya Marc'ın bir astarını kendi uzatma sınıfınıza sarabilirsiniz:
public static class PropertyExtension{
public static void SetPropertyValue(this object obj, string propName, object value)
{
obj.GetType().GetProperty(propName).SetValue(obj, value, null);
}
}
ve şöyle deyin:
myObject.SetPropertyValue("myProperty", "myValue");
İyi bir ölçü için, bir özellik değeri elde etmek için bir yöntem ekleyelim:
public static object GetPropertyValue(this object obj, string propName)
{
return obj.GetType().GetProperty(propName).GetValue (obj, null);
}
Bunun gibi bir şey kullanın:
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);
}
}
veya
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);
}
}
Alanlara benzer bir şekilde de erişebilirsiniz:
var obj=new MyObject();
FieldInfo fi = obj.GetType().
GetField("Name", BindingFlags.NonPublic | BindingFlags.Instance);
fi.SetValue(obj,value)
Yansıması ile her şey açık bir kitap olabilir :) Örneğimde özel bir örnek seviyesi alanına bağlanıyoruz.
Özellik adlarını kullanarak bir Nesnenin özelliklerini başka bir Nesneden toplu olarak atamak istediğinizde bunu deneyebilirsiniz:
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;
}
}
}
}
Ben sadece ilk seviye Özellikleri değil, aynı zamanda herhangi bir derinlikte verilen nesnede iç içe özellikleri ayarlamaya izin veren bir Nuget paketi yayınladım.
İşte paket
Bir nesnenin özelliğinin değerini kökünden yoluna göre ayarlar.
Nesne karmaşık bir nesne olabilir ve özellik çok düzeyli derin iç içe özellik olabilir veya doğrudan kökün altındaki bir özellik olabilir. ObjectWriter
özelliği özellik yolu parametresini kullanarak bulur ve değerini günceller. Özellik yolu, sınırlayıcı dize parametresi tarafından ayrılmış, kökten ayarlamak istediğimiz son düğüm özelliğine ziyaret edilen özelliklerin eklenmiş adlarıdır.
Kullanımı:
Özellikleri doğrudan nesne kökünün altında ayarlamak için:
Yani. LineItem
sınıfın int özelliği varItemId
LineItem lineItem = new LineItem();
ObjectWriter.Set(lineItem, "ItemId", 13, delimiter: null);
Yuvalanmış özelliği, nesne kökünün altında birden çok düzey ayarlamak için:
Yani. Invite
sınıf, adlı bir özelliğe State
sahiptir ve bu özelliği Invite
(Davet türü) adlı bir özelliğe Recipient
sahiptir.Id
.
İşleri daha da karmaşık hale getirmek için, State
özellik bir referans türü değil, bir struct
.
Nesne ağacının altındaki Id özelliğini (“outlook” dizesi değerine) tek bir satırda nasıl ayarlayacağınız aşağıda açıklanmıştır.
Invite invite = new Invite();
ObjectWriter.Set(invite, "State_Invite_Recipient_Id", "outlook", delimiter: "_");
MarcGravell'in önerisine dayanarak, aşağıdaki statik yöntemi oluşturdum.Yöntem genel olarak FastMember kullanarak kaynak nesneden hedefe eşleşen tüm özellikleri atar
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);
kaynak: devx.com/vb2themax/Tip/19599