প্রতিবিম্ব ব্যবহার করে আমি কি সি # তে একটি ব্যক্তিগত পাঠযোগ্য ক্ষেত্র পরিবর্তন করতে পারি?


115

আমি ভাবছি, যেহেতু প্রতিবিম্ব ব্যবহার করে অনেক কিছু করা যায়, তাই আমি কি নির্মাণের কাজ শেষ করার পরে একটি ব্যক্তিগত পাঠযোগ্য ক্ষেত্র পরিবর্তন করতে পারি?
(দ্রষ্টব্য: শুধু কৌতূহল)

public class Foo
{
 private readonly int bar;

 public Foo(int num)
 {
  bar = num;
 }

 public int GetBar()
 {
  return bar;
 }
}

Foo foo = new Foo(123);
Console.WriteLine(foo.GetBar()); // display 123
// reflection code here...
Console.WriteLine(foo.GetBar()); // display 456

উত্তর:


151

আপনি পারেন:

typeof(Foo)
   .GetField("bar",BindingFlags.Instance|BindingFlags.NonPublic)
   .SetValue(foo,567);

2
আপনি অবশ্যই ঠিক বলেছেন। আমার ক্ষমা। এবং হ্যাঁ, আমি চেষ্টা করেছিলাম, তবে আমি কোনও সমর্থন ক্ষেত্র ব্যবহার না করে সরাসরি পঠনযোগ্য সম্পত্তি সেট করার চেষ্টা করেছি। আমি যা চেষ্টা করেছি তা বোধগম্য হয়নি। আপনার সমাধানটি পুরোপুরি সূক্ষ্মভাবে কাজ করে (আবার পরীক্ষিত, সঠিকভাবে এবার)
সেজে পূরপ্রে

আমরা মোখ দিয়ে এটি কীভাবে করতে পারি?
l -'''''--------- '' '' '' '' '' '

ডটনেট কোর 3.0 এ এটি আর সম্ভব নয়। একটি সিস্টেম.ফিল্ড অ্যাক্সেস এক্সসেপশনটি এইভাবে ছুঁড়ে দেওয়া হয়েছে: "'ফু' টাইপ করার পরে আরম্ভিক স্ট্যাটিক ফিল্ড 'বার' সেট করা যায় না" "
ডেভিড পারফোরস

54

সুস্পষ্ট বিষয় হ'ল এটি চেষ্টা করা:

using System;
using System.Reflection;

public class Test
{
    private readonly string foo = "Foo";

    public static void Main()
    {
        Test test = new Test();
        FieldInfo field = typeof(Test).GetField
            ("foo", BindingFlags.Instance | BindingFlags.NonPublic);
        field.SetValue(test, "Hello");
        Console.WriteLine(test.foo);
    }        
}

এটি কাজ করে। (জাভাটির বিভিন্ন বিধি রয়েছে, আকর্ষণীয়ভাবে - আপনাকে স্পষ্টভাবে Fieldঅ্যাক্সেসযোগ্য হিসাবে সেট করতে হবে এবং এটি কেবল উদাহরণস্বরূপ ক্ষেত্রগুলির জন্য যেভাবেই চলবে))


4
আহমেদ - তবে আমরা এটি করার জন্য ভাষাটি ব্যবহার করছি না, তাই ভাষা
অনুমানটি

4
হ্যাঁ - অনেক কিছুই করা যায় যা ভাষা যা চায় তা "ব্রেক" করে। আপনি একাধিকবার টাইপ ইনিশিয়ালাইজার চালাতে পারেন।
জন স্কিটি

28
আমি এও নোট করি যে আপনি আজ কিছু প্রয়োগ করতে পারছেন তার অর্থ এই নয় যে আপনি সর্বকালের জন্য প্রতিটি বাস্তবায়ন করতে পারবেন। আমি এমন কোনও জায়গার বিষয়ে অবগত নই যেখানে আমরা নথী করি যে কেবল পাঠ ক্ষেত্রগুলি প্রতিবিম্বের মাধ্যমে পরিবর্তনযোগ্য হতে হবে। যতদূর আমি জানি, সিএলআইয়ের যথাযথ বাস্তবায়ন কেবল পঠনযোগ্য ক্ষেত্রগুলি বাস্তবায়নের জন্য পুরোপুরি মুক্ত that
এরিক লিপার্ট

3
যদিও এটি ভাল নয়, কারণ এমন কিছু মামলা রয়েছে যখন আমার ক্লাসটি তৈরির প্রয়োজন ছিল তার চেয়ে বেশি প্রসারিত করা। যখন এটি সুপরিকল্পিত হয় তখন সর্বদা এনক্যাপসুলেশনকে ওভাররাইড করার একটি উপায় থাকা উচিত। একমাত্র বিকল্পগুলি হ'ল গৌরবময় এবং কাঠামোর অংশটি পুনরায় লিখন ছাড়া কখনও কখনও সম্ভব হয় না।
প্রবাহতাড়িত

5
@ ড্রিফটার: এই মুহুর্তে, আপনি নিজেকে ব্যথার জগতে উন্মুক্ত করছেন। আপনি বর্তমান বাস্তবায়ন বিশদের উপর নির্ভর করছেন যা সহজেই ভবিষ্যতের সংস্করণে পরিবর্তিত হতে পারে।
জন স্কিটি

11

আমি অন্যান্য উত্তরের সাথে একমত যে এটি সাধারণত এবং বিশেষত ই লিপার্টের মন্তব্যে কার্যকর হয় যে এটি নথিভুক্ত আচরণ নয় এবং তাই ভবিষ্যতের প্রমাণ কোড নয়।

তবে আমরা আরও একটি বিষয় লক্ষ্য করেছি। আপনি যদি সীমাবদ্ধ অনুমতি নিয়ে কোনও পরিবেশে আপনার কোড চালাচ্ছেন তবে আপনি ব্যতিক্রম পেতে পারেন।

আমাদের সবেমাত্র একটি কেস হয়েছে যেখানে আমাদের কোডগুলি আমাদের মেশিনগুলিতে সূক্ষ্মভাবে কাজ করে, তবে VerificationExceptionকোডটি একটি সীমাবদ্ধ পরিবেশে চলার সময় আমরা একটি পেলাম । অপরাধীটি কেবল পাঠযোগ্য ক্ষেত্রের সেটারের প্রতিচ্ছবি ছিল। যখন আমরা সেই ক্ষেত্রের পঠনযোগ্য সীমাবদ্ধতা সরিয়েছিলাম তখন এটি কাজ করেছিল।


2
কোন পরিবেশগুলি যাচাইকরণের
ধারণাটি ছুঁড়েছে

4

আপনি কেন এমনভাবে এনক্যাপসুলেশনটি ভাঙতে চান তা জিজ্ঞাসা করেছিলেন।

সত্তা হাইড্রেট করতে আমি একটি সত্তা সহায়ক শ্রেণি ব্যবহার করি। এটি একটি নতুন খালি সত্তার সমস্ত বৈশিষ্ট্য পাওয়ার জন্য প্রতিবিম্ব ব্যবহার করে এবং ফলসেটের কলামের সাথে সম্পত্তি / ক্ষেত্রের নামের সাথে মেলে এবং এটি সম্পত্তিinfo.setvalue () ব্যবহার করে সেট করে।

আমি চাই না যে অন্য কেউ মান পরিবর্তন করতে সক্ষম হন, তবে আমি প্রতিটি সত্তার জন্য কাস্টম কোড হাইড্রেশন পদ্ধতিতে সমস্ত প্রচেষ্টা নিতে চাই না।

আমার বেশিরভাগ সঞ্চিত প্রোকস ফলাফলগুলি রিটার্ন দেয় যা সরাসরি টেবিল বা দৃশ্যের সাথে সামঞ্জস্য করে না, তাই কোড জেনার্স ওআরএম আমার পক্ষে কিছুই করে না।


1
আমি এটি কিছু এপিআই সীমাবদ্ধতাগুলি অতিক্রম করার জন্য ব্যবহার করেছি যেখানে মানটি হয় হার্ডকোডযুক্ত, অথবা একটি কনফিগার ফাইলের প্রয়োজন হয় যা আমি সরবরাহ করতে পারব না। (
অ্যাসেমব্লিউগুলি

3

অনিরাপদ ব্যবহার করে এটি করার আর একটি সহজ উপায় (বা আপনি ক্ষেত্রটি DLLImport এর মাধ্যমে কোনও সি পদ্ধতিতে পাস করতে পারেন এবং এটি সেখানে সেট করতে পারেন)।

using System;

namespace TestReadOnly
{
    class Program
    {
        private readonly int i;

        public Program()
        {
            i = 66;
        }

        private unsafe void ForceSet()
        {
            fixed (int* ptr = &i) *ptr = 123;
        }

        static void Main(string[] args)
        {
            var program = new Program();
            Console.WriteLine("Contructed Value: " + program.i);
            program.ForceSet();
            Console.WriteLine("Forced Value: " + program.i);
        }
    }
}

2

উত্তর হ্যাঁ, তবে আরও গুরুত্বপূর্ণ:

তুমি কেন চাইবে? ইচ্ছাকৃতভাবে এনক্যাপসুলেশন ভাঙ্গা আমার কাছে ভয়াবহভাবে খারাপ ধারণা বলে মনে হচ্ছে।

পঠনযোগ্য বা ধ্রুবক ক্ষেত্রটি পরিবর্তনের জন্য প্রতিবিম্ব ব্যবহার করা মরফির আইনের সাথে অনানুষ্ঠানিক ফলাফলগুলির আইনকে সংযুক্ত করার মতো ।


1
উত্তরটি উপরে বর্ণিত "জাস্ট কৌতূহল"।
রন ক্লেইন

এমন সময় আছে যখন আমি নিজের সেরা কোডটি লেখার জন্য নিজেকে কেবল এই কৌশলটি করতেই দেখি। কেস পয়েন্টে - elegantcode.com/2008/04/17/testing-a-Meshiphip-provider
স্পার্কার

3
আমিও ইউনিট টেস্টিং প্রকল্পগুলিতে এই কৌশলটি ডিফল্ট মানগুলিকে ওভাররাইড করতে ব্যবহার করি যা কোনও ব্যবসায়ের কোডে পরিবর্তন করা উচিত নয় ...
কোয়েন

এবং আমি পরীক্ষার উদ্দেশ্যে বেস ক্লাসের লাইব্রেরিতে ব্যক্তিগত অভ্যন্তরীণ বৈশিষ্ট্যগুলি সেট করার চেষ্টা করছিলাম, বিশেষত সদস্যপদ এপিআই, যেখানে এমএস সমস্ত ব্যক্তিগত, আভ্যন্তরীণ এবং সম্পত্তিগুলিতে কোনও সেটার ছাড়াই চিহ্নিত করেছিল। এটির জন্য কেসগুলি রয়েছে, তবে প্রশ্নটি আপনার নিয়ন্ত্রণে থাকা কোনও এপিআইতে প্রয়োগ করা হলে আপনি সঠিক
চাদ গ্রান্ট

3
এমন পরিস্থিতি রয়েছে যেখানে এটি বোধগম্য হয়। এন / হাইবারনেটের মতো ও / আর ম্যাপাররা হাইড্রেশনের জন্য সর্বদা এটি করে থাকে, কারণ এটিই আপনি প্রথম স্থানে অবিচ্ছিন্ন সত্তার জন্য ডেটা এনক্যাপসুলেশন বাস্তবায়ন করতে পারেন।
ক্রিস

2

এটি করবেন না।

আমি কেবল একটি পরাবাস্তব বাগ ঠিক করতে একদিন ব্যয় করেছি যেখানে বস্তুগুলি তাদের নিজস্ব ঘোষিত ধরণের হতে পারে না।

পঠনযোগ্য ক্ষেত্রটি পরিবর্তন করে একবার কাজ করেছে। তবে আপনি যদি আবার এটি সংশোধন করার চেষ্টা করেন তবে আপনি এমন পরিস্থিতিগুলি পেতে পারেন:

SoundDef mySound = Reflection_Modified_Readonly_SoundDef_Field;
if( !(mySound is SoundDef) )
    Log("Welcome to impossible-land!"); //This would run

সুতরাং এটি করবেন না।

এটি ছিল মনো রানটাইম (ইউনিটির গেম ইঞ্জিন)।


2
এফওয়াইআই - ইউনিটি ইঞ্জিনকে এই জাতীয় গভীর সি # ভাষা-নির্দিষ্ট প্রশ্নের কার্যকরভাবে উত্তর দেওয়ার জন্য ব্যবহার করা যাবে না কারণ ityক্যটি সি # এর নিজস্ব সংকলনটি সম্পাদন করে যেমন .সিএস স্ক্রিপ্ট ছিল, এক অর্থে। আমি বলছি না যে আপনার পয়েন্টটি বৈধ নয়, তবে এটি অবশ্যই ইউনিটি ইঞ্জিন এবং সি # একসাথে নির্দিষ্ট।
ডেভ জেলিসন

0

আমি কেবল এটি যুক্ত করতে চাই যে আপনি যদি ইউনিট পরীক্ষার জন্য এই জিনিসগুলি করার দরকার হয় তবে আপনি ব্যবহার করতে পারেন:

ক) বেসরকারী ক্লাস

খ) আপনার এখনও একটি বেসরকারী বিষয় উদাহরণ প্রয়োজন হবে, তবে আপনি ভিজ্যুয়াল স্টুডিও সহ "অ্যাকসেসর" অবজেক্ট তৈরি করতে পারেন। কীভাবে: প্রাইভেট অ্যাকসেসারগুলি পুনরায় জন্মানো

আপনি যদি ইউনিট পরীক্ষার বাইরে আপনার কোডে কোনও সামগ্রীর ব্যক্তিগত ক্ষেত্রগুলি সেট করে থাকেন, তবে এটি "কোড গন্ধ" এর একটি উদাহরণ হতে পারে think আমি মনে করি যে আপনি কেবল তৃতীয় পক্ষের সাথে ডিল করছেন যদি আপনি এটি করতে চান তবে কেবলমাত্র অন্য কারণ গ্রন্থাগার এবং আপনি লক্ষ্য শ্রেণীর কোড পরিবর্তন করতে পারবেন না। তারপরেও, আপনি সম্ভবত তৃতীয় পক্ষের সাথে যোগাযোগ করতে চান, আপনার পরিস্থিতিটি ব্যাখ্যা করতে পারেন এবং দেখুন যে তারা এগিয়ে না যায় এবং আপনার প্রয়োজনীয়তা সামঞ্জস্য করার জন্য তাদের কোডটি পরিবর্তন করে না।

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