প্রতিবিম্ব ব্যবহার করে বস্তুর সম্পত্তি সেট করুন


323

সি # তে কি এমন কোনও উপায় আছে যেখানে আমি কোনও সামগ্রীর সম্পত্তি সেট করার জন্য প্রতিবিম্বটি ব্যবহার করতে পারি?

উদা:

MyObject obj = new MyObject();
obj.Name = "Value";

আমি obj.Nameপ্রতিবিম্ব সঙ্গে সেট করতে চান । কিছুটা এইরকম:

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

এটি করার কোন উপায় আছে?

উত্তর:


391

হ্যাঁ, আপনি ব্যবহার করতে পারেন 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);
}

73
আপনি যদি সমস্ত স্ট্রিংয়ের সাথে কাজ না করে থাকেন তবে আপনি প্রথমে ডেটা রূপান্তর করতে চান: var val = Convert.ChangeType(propValue, propInfo.PropertyType); উত্স: devx.com/vb2themax/Tip/19599
LostNomad311

4
বিকল্পভাবে, আপনি ব্যবহার করতে পারেনobj.GetType().GetProperty("Name")?.GetSetMethod()?.Invoke(...)
টেকফিল্ড

1
CanWrite=Falseপ্রকারের জন্য মূল্য নির্ধারণ করা অসম্ভব , তাই না?
টি.ডুডো

287

আপনি এটি করতে পারেন:

Type type = target.GetType();

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

prop.SetValue (target, propertyValue, null);

যেখানে লক্ষ্যটি হল সেই বস্তু যা তার সম্পত্তি সেট করবে।


11
আমি আজ খুব একই জিনিস করেছি। উপরেরটি দুর্দান্ত কাজ করে, স্পষ্টতই এটিকে ব্যবহারের চেষ্টা করার আগে একটি নাল চেক করা উচিত।
অ্যান্টনি স্কট

3
@ অ্যান্টনিস্কট আমার মনে হয় আপনি যদি ভুল সম্পত্তিটি চালাচ্ছেন তবে আপনি জানতে চান আপনি "চুপচাপ ব্যর্থ হন" এটি একটি খারাপ পথ বলে মনে হচ্ছে।
জিহ

3
@ জিহ আমি আপনার বক্তব্যটি দেখতে পাচ্ছি, তবে এটি সত্যিকারের পরিস্থিতির উপর নির্ভর করে।
অ্যান্টনি স্কট

94

প্রতিফলন, মূলত, যেমন

myObject.GetType().GetProperty(property).SetValue(myObject, "Bob", null);

বা সুবিধা এবং কার্যকারিতা উভয় ক্ষেত্রে সহায়তা করার জন্য গ্রন্থাগার রয়েছে; উদাহরণস্বরূপ ফাস্টমেম্বারের সাথে :

var wrapped = ObjectAccessor.Create(obj); 
wrapped[property] = "Bob";

(এটি কোনও সম্পত্তি বনাম ক্ষেত্র কিনা তা আগে থেকে জানা প্রয়োজন না হওয়ার সুবিধাও রয়েছে)


বাহ, মার্জ থেকে কিছুটা বিভ্রান্ত হয়ে পড়েছে, তবে আমি আপনার উত্তরটি আবার খুঁজে পেয়েছি! আপনাকে ধন্যবাদ, আপনি একটি 'স্বীকার করি' প্রাপ্য, কিন্তু আমার থ্রেড মিশে গিয়ে তৈরি হয় যেহেতু :( ধন্যবাদ আবার!
halfpastfour.am

@ মার্কগ্রাভেল, আমি ফাস্টমেমবারের দিকে তাকিয়ে ছিলাম এবং এটি বেশ আকর্ষণীয়। আপনার এই মহান lib ব্যবহার করার জন্য নিছক প্রাণঘাতী আমাদের জন্য কোথাও কোনও সূচনা / টিউটোরিয়াল শুরু করছেন?
সুধাংশু মিশ্র

আমি কিভাবে ফাস্টমেম্বারের মাধ্যমে সম্পত্তিটির ধরণ পেতে পারি?
বলেছেন রুহুল্লাহ আলেমে

@ জাহান অ্যাক্সেসর => গেটমেমবার্স => সদস্য => প্রকার
মার্ক গ্র্যাভেল

দুর্দান্ত উত্তর! একজন অনিয়ালিকার সম্পর্কে ভাল কথাটি এটি বুঝতে খুব দ্রুত হয়, যেহেতু এমন কোনও ব্যবহারকারীর নাম নেই যার মধ্যে ভেরিয়েবলগুলির মধ্যে নিজের পক্ষে কোনও ধারণা বোধ করা সম্ভব না ..
বাসটিয়ান

27

অথবা আপনি নিজের এক্সটেনশান ক্লাসের মধ্যে মার্কের একটি লাইনার মোড়ানো করতে পারেন:

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

14

হ্যাঁ, ব্যবহার করে System.Reflection:

using System.Reflection;

...

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

13

এর মতো কিছু ব্যবহার করুন:

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

2
যে অংশটি আপনি সম্পত্তির ধরণটি পান এবং তারপরে নিক্ষেপ করেন তা আমার জন্য সত্যই কার্যকর ছিল। ইহা যাদুর মত কাজ করে। আপনাকে ধন্যবাদ
মার্ক

12

আপনি সিমিলার পদ্ধতিতে ক্ষেত্রগুলি অ্যাক্সেস করতে পারেন:

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

প্রতিবিম্ব সহ সবকিছুই একটি উন্মুক্ত বই হতে পারে :) আমার উদাহরণে আমরা একটি ব্যক্তিগত উদাহরণ স্তরের ক্ষেত্রে বাধ্য।


8

আপনি যখন সম্পত্তিটির নাম ব্যবহার করে অন্য কোনও অবজেক্টের থেকে কোনও অবজেক্টের বৈশিষ্ট্য-ভরকরণ করতে চান তখন আপনি এটি ব্যবহার করে দেখতে পারেন:

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

2
হাই এবং স্ট্যাক ওভারফ্লোতে আপনাকে স্বাগতম। দয়া করে আপনার কোডটি সঠিকভাবে ফর্ম্যাট করুন এবং এটি কেবল আপনার পোস্টে ফেলে দেবেন না, এটি অন্যদের আপনার উত্তর বুঝতে সহায়তা করবে।
থ্রিএফএক্স

0

আমি সবেমাত্র একটি নুগেট প্যাকেজ প্রকাশ করেছি যা কেবলমাত্র প্রথম স্তরের বৈশিষ্ট্যগুলিকেই নয় বরং যে কোনও গভীরতায় প্রদত্ত বস্তুর মধ্যে নেস্টেড বৈশিষ্ট্যগুলি সেট আপ করতে দেয়।

প্যাকেজটি এখানে

মূল থেকে কোনও পথে কোনও বস্তুর সম্পত্তির মান সেট করে।

অবজেক্টটি একটি জটিল বস্তু হতে পারে এবং সম্পত্তিটি বহু স্তরের গভীর নেস্টেড সম্পত্তি হতে পারে বা এটি সরাসরি মূলের নীচে সম্পত্তি হতে পারে। ObjectWriterসম্পত্তি প্যারামিটার ব্যবহার করে সম্পত্তিটি খুঁজে পাবে এবং এর মান আপডেট করবে update সম্পত্তি পথ হ'ল মূল থেকে শেষ নোড বৈশিষ্ট্য যা আমরা সেট করতে চাই সেগুলি পরিমার্জিত স্ট্রিং প্যারামিটার দ্বারা বিভাজনযুক্ত সংখ্যার সংযুক্ত নাম।

ব্যবহার:

সরাসরি বস্তুর মূলের নীচে বৈশিষ্ট্যগুলি সেট আপ করার জন্য:

অর্থাৎ। LineItemশ্রেণীর একটি সংখ্যার সম্পত্তি বলা হয়ItemId

LineItem lineItem = new LineItem();

ObjectWriter.Set(lineItem, "ItemId", 13, delimiter: null);

বস্তুর মূলের নীচে নেস্টেড সম্পত্তি একাধিক স্তর স্থাপনের জন্য:

অর্থাৎ। Inviteশ্রেণীর একটি সম্পত্তি বলা হয় State, যার একটি সম্পত্তি থাকে Invite(আমন্ত্রিত প্রকারের), যার একটি সম্পত্তি বলা হয় Recipient, যার একটি সম্পত্তি বলা হয় Id

জিনিসগুলিকে আরও জটিল করার জন্য, Stateসম্পত্তিটি কোনও রেফারেন্স টাইপ নয়, এটি একটি astruct

এখানে আপনি কীভাবে একক লাইনে অবজেক্ট ট্রি এর নীচে আইডি সম্পত্তি ("আউটলুক" এর স্ট্রিং মান) সেট করতে পারেন।

Invite invite = new Invite();

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

0

মার্কগ্রাভেলের পরামর্শের ভিত্তিতে, আমি নিম্নলিখিত স্থিতিশীল পদ্ধতিটি তৈরি করেছি method পদ্ধতিটি সাধারণভাবে উত্স অবজেক্ট থেকে সমস্ত মিলে যাওয়া বৈশিষ্ট্যগুলিকে ফাস্টমেমার ব্যবহার করে লক্ষ্য হিসাবে নির্ধারিত করে

 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);
            }
        }
    }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.