প্রতিবিম্ব মাধ্যমে ব্যক্তিগত সম্পত্তি সেট করা সম্ভব?


125

প্রতিবিম্বের মাধ্যমে কি আমি একটি ব্যক্তিগত সম্পত্তি সেট করতে পারি?

public abstract class Entity
{
    private int _id;
    private DateTime? _createdOn;
    public virtual T Id
    {
        get { return _id; }
        private set { ChangePropertyAndNotify(ref _id, value, x => Id); }
    }
    public virtual DateTime? CreatedOn
    {
        get { return _createdOn; }
        private set { ChangePropertyAndNotify(ref _createdOn, value, x => CreatedOn); }
    }
}

আমি নিম্নলিখিতটি চেষ্টা করেছি এবং এটি কার্যকর হয় না, যেখানে tএক ধরণের প্রতিনিধিত্ব করে Entity:

var t = typeof(Entity);
var mi = t.GetMethod("set_CreatedOn", BindingFlags.Instance | BindingFlags.NonPublic);

আমার ধারণা আমি এটি করতে পারি তবে আমি এটি কার্যকর করতে পারি না।


2
আমি জানি যে এটি দেরি হয়ে গেছে, তবে এই চিন্তাভাবনার জন্য একটি প্রয়োজনীয়তা পেয়েছি যে আমি আমার 'কেন' ভাগ করব। কিছু তৃতীয় পক্ষের সফ্টওয়্যারটিতে আমার অসুবিধা কাটিয়ে উঠতে হবে। বিশেষত, আমি স্ফটিক রিপোর্টগুলি এক্সপোর্টটোস্ট্রিম পদ্ধতিটি ব্যবহার করছিলাম। এই পদ্ধতিটি যেভাবে লেখা হয়েছিল, প্রবাহের অভ্যন্তরীণ বাফারে অ্যাক্সেসের অনুমতি ছিল না। ব্রাউজারে প্রতিবেদনটি প্রেরণ করতে, আমাকে স্ট্রিমটি একটি নতুন বাফারে (100 কে +) কপি করতে হয়েছিল, তারপরে এটি প্রেরণ করতে হবে। প্র্রাইজ অবজেক্টে প্রাইভেট '_ এক্সপোজেবল' ক্ষেত্রটি 'সত্য' হিসাবে সেট করে আমি প্রতিটি অনুরোধে 100 কে + বরাদ্দ সংরক্ষণ করে সরাসরি অভ্যন্তরীণ বাফারটি প্রেরণ করতে সক্ষম হয়েছি।
রায়

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

2
অন্য ব্যবহারের পরিস্থিতি: ডেটা আমদানির সময় স্বয়ংক্রিয়ভাবে উত্পন্ন ক্ষেত্রগুলি "তৈরির তারিখ" সেট করা setting
এভিনিস

আর যদি সম্ভব হয় তবে আমি কেন আগ্রহী। এই প্রশ্নটি শেষ করেই আমি শেষ করেছি।
কালেব মাউয়ার

উত্তর:


94
t.GetProperty("CreatedOn")
    .SetValue(obj, new DateTime(2009, 10, 14), null);

সম্পাদনা: যেহেতু সম্পত্তিটি নিজেই প্রকাশ্য, তাই এটি সন্ধানের জন্য আপনার স্পষ্টতই ব্যবহারের প্রয়োজন হবে না BindingFlags.NonPublicSetValueসেটারের কম অ্যাক্সেসযোগ্যতা থাকা সত্ত্বেও কল করা আপনার প্রত্যাশা অনুযায়ী এখনও তা করে।


5
ন্যায়সঙ্গত হওয়ার জন্য, এটি বিশ্বাসের স্তরের উপর নির্ভর করে, তবে উত্তরটি বৈধ বলে মনে হচ্ছে।
মার্ক গ্র্যাভেল

4
সিস্টেমের মধ্যে সম্পত্তি সেট পদ্ধতি পাওয়া যায় নি efনির্ধারণ.রুনটাইমপ্রপার্টিআইএনফো.সেটভ্যালু (অবজেক্ট অবজেক্ট, অবজেক্ট ভ্যালু, বাইন্ডিংফ্ল্যাজস আহ্বান করা হয়েছে, বাইন্ডার বাইন্ডার, অবজেক্ট [] ইনডেক্স,
কালচারিআইনফো

1
আমি যদি ভার্চুয়াল সম্পত্তি না ব্যবহার করি তবে এটি আমার পক্ষে ভাল কাজ করে। আমি যদি ভার্চুয়াল সম্পত্তি নিয়ে সেটওয়ালু করি তবে এটি কাজ করবে বলে মনে হয় না।
JonathanPeel

105

হ্যাঁ, এটি:

/// <summary>
/// Returns a _private_ Property Value from a given Object. Uses Reflection.
/// Throws a ArgumentOutOfRangeException if the Property is not found.
/// </summary>
/// <typeparam name="T">Type of the Property</typeparam>
/// <param name="obj">Object from where the Property Value is returned</param>
/// <param name="propName">Propertyname as string.</param>
/// <returns>PropertyValue</returns>
public static T GetPrivatePropertyValue<T>(this object obj, string propName)
{
    if (obj == null) throw new ArgumentNullException("obj");
    PropertyInfo pi = obj.GetType().GetProperty(propName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
    if (pi == null) throw new ArgumentOutOfRangeException("propName", string.Format("Property {0} was not found in Type {1}", propName, obj.GetType().FullName));
    return (T)pi.GetValue(obj, null);
}

/// <summary>
/// Returns a private Property Value from a given Object. Uses Reflection.
/// Throws a ArgumentOutOfRangeException if the Property is not found.
/// </summary>
/// <typeparam name="T">Type of the Property</typeparam>
/// <param name="obj">Object from where the Property Value is returned</param>
/// <param name="propName">Propertyname as string.</param>
/// <returns>PropertyValue</returns>
public static T GetPrivateFieldValue<T>(this object obj, string propName)
{
    if (obj == null) throw new ArgumentNullException("obj");
    Type t = obj.GetType();
    FieldInfo fi = null;
    while (fi == null && t != null)
    {
        fi = t.GetField(propName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
        t = t.BaseType;
    }
    if (fi == null) throw new ArgumentOutOfRangeException("propName", string.Format("Field {0} was not found in Type {1}", propName, obj.GetType().FullName));
    return (T)fi.GetValue(obj);
}

/// <summary>
/// Sets a _private_ Property Value from a given Object. Uses Reflection.
/// Throws a ArgumentOutOfRangeException if the Property is not found.
/// </summary>
/// <typeparam name="T">Type of the Property</typeparam>
/// <param name="obj">Object from where the Property Value is set</param>
/// <param name="propName">Propertyname as string.</param>
/// <param name="val">Value to set.</param>
/// <returns>PropertyValue</returns>
public static void SetPrivatePropertyValue<T>(this object obj, string propName, T val)
{
    Type t = obj.GetType();
    if (t.GetProperty(propName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) == null)
        throw new ArgumentOutOfRangeException("propName", string.Format("Property {0} was not found in Type {1}", propName, obj.GetType().FullName));
    t.InvokeMember(propName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.SetProperty | BindingFlags.Instance, null, obj, new object[] { val });
}

/// <summary>
/// Set a private Property Value on a given Object. Uses Reflection.
/// </summary>
/// <typeparam name="T">Type of the Property</typeparam>
/// <param name="obj">Object from where the Property Value is returned</param>
/// <param name="propName">Propertyname as string.</param>
/// <param name="val">the value to set</param>
/// <exception cref="ArgumentOutOfRangeException">if the Property is not found</exception>
public static void SetPrivateFieldValue<T>(this object obj, string propName, T val)
{
    if (obj == null) throw new ArgumentNullException("obj");
    Type t = obj.GetType();
    FieldInfo fi = null;
    while (fi == null && t != null)
    {
        fi = t.GetField(propName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
        t = t.BaseType;
    }
    if (fi == null) throw new ArgumentOutOfRangeException("propName", string.Format("Field {0} was not found in Type {1}", propName, obj.GetType().FullName));
    fi.SetValue(obj, val);
}

7
কারও এলিজ চুলগুলি নিরাপদে রাখার জন্য (যেটি কেবল আমার মাথার উপরে টানা হয়েছে): এটি সিলভারলাইট রানটাইমগুলিতে কাজ করবে না: এমএসডিএন.মাইক্রোসফট
মার্ক উইট্কে

সেটভ্যালু ইনভোকেম্বরের চেয়ে ভাল হবে, যেহেতু প্রাক্তন সমর্থন পাসিং সূচকটি
ক্রিস জিউ

8

আপনি কোডের মাধ্যমে উদ্ভূত প্রকার থেকে ব্যক্তিগত সেটটার অ্যাক্সেস করতে পারেন

public static void SetProperty(object instance, string propertyName, object newValue)
{
    Type type = instance.GetType();

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

    prop.SetValue(instance, newValue, null);
}

+1, তবে এখানে কেবল একটি নোট। বেসটাইপটিতে আপনারা আশা করছেন এমন সমস্ত বৈশিষ্ট্য থাকা উচিত। আপনি যদি কোনও সম্পত্তি আড়াল করে রাখছেন (আপনি এটি করেছেন তা মনে না করে), এর ফলে কিছু চুল টানা যেতে পারে।
6:44 এ ওফ্ল্যাক করুন

3

এগুলির কোনওটিই আমার পক্ষে কাজ করেনি, এবং আমার সম্পত্তির নামটি অনন্য ছিল, তাই আমি কেবল এটি ব্যবহার করেছি:

public static void SetPrivatePropertyValue<T>(T obj, string propertyName, object newValue)
{
    // add a check here that the object obj and propertyName string are not null
    foreach (FieldInfo fi in obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic))
    {
        if (fi.Name.ToLower().Contains(propertyName.ToLower()))
        {
            fi.SetValue(obj, newValue);
            break;
        }
    }
}

0
    //mock class
    public class Person{
        public string Name{get; internal set;}
    }

    // works for all types, update private field through reflection
    public static T ReviveType<T>(T t, string propertyName, object newValue){
        // add a check here that the object t and propertyName string are not null
        PropertyInfo pi = t.GetType().GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance);
         pi.SetValue(t, newValue, null); 
        return t;
    }

    // check the required function
    void Main()
    {
        var p = new Person(){Name="John"};
        Console.WriteLine("Name: {0}",p.Name);

        //box the person to object, just to see that the method never care about what type you pass it
        object o = p;
        var updatedPerson = ReviveType<Object>(o, "Name", "Webber") as Person;

         //check if it updated person instance
        Console.WriteLine("Name: {0}",updatedPerson.Name);
    }



// Console Result: -------------------
Name: John
Name: Webber
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.