একটি ইভেন্ট হ্যান্ডলার ইতিমধ্যে যুক্ত করা হয়েছে?


183

কোনও ইভেন্টের হ্যান্ডলারটি কোনও বস্তুর সাথে যুক্ত করা হয়েছে কি তা বলার উপায় আছে? আমি সেশন স্টেটে / আউট অবজেক্টের একটি তালিকা সিরিয়ালাইজ করছি যাতে আমরা এসকিউএল ভিত্তিক সেশন স্টেটটি ব্যবহার করতে পারি ... তালিকার কোনও বস্তুর কোনও সম্পত্তি পরিবর্তন হলে এটি পতাকাঙ্কিত করা দরকার, যা ইভেন্ট হ্যান্ডলার আগে সঠিকভাবে যত্ন নিয়েছিল which । তবে এখন যখন বস্তুগুলি ডিজিট্রাইজ করা হয় এটি ইভেন্ট হ্যান্ডলারটি পাচ্ছে না।

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

এটি কেবল উপেক্ষা করার পক্ষে এটি যথেষ্ট নিরাপদ, তবে হ্যান্ডলারটি ইতিমধ্যে যুক্ত হয়েছে কিনা তা পরীক্ষা করে আমি এটি এতটাই পরিষ্কার করে তুলছি যে আমি কেবল একবারই এটি করি।

এটা কি সম্ভব?

সম্পাদনা: ইভেন্ট হ্যান্ডলারগুলি কী যুক্ত করা হয় তা সম্পর্কে অগত্যা আমার সম্পূর্ণ নিয়ন্ত্রণ নেই, সুতরাং কেবল নাল পরীক্ষা করা যথেষ্ট ভাল নয়।


উত্তর:


123

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

public bool IsEventHandlerRegistered(Delegate prospectiveHandler)
{   
    if ( this.EventHandler != null )
    {
        foreach ( Delegate existingHandler in this.EventHandler.GetInvocationList() )
        {
            if ( existingHandler == prospectiveHandler )
            {
                return true;
            }
        }
    }
    return false;
}

এবং এটি সহজেই "হ্যান্ডলারটি সেখানে না থাকলে যোগ করুন" হয়ে ওঠার জন্য সহজেই পরিবর্তিত হতে পারে। আপনি ক্লাসের নাড়িভুঁড়ি যে ঘটনা প্রকাশিত হচ্ছে অ্যাক্সেস নেই থাকে, তাহলে আপনি এক্সপ্লোর করার প্রয়োজন হতে পারে -=এবং +=যেমন @Lou ফ্রাঙ্কো দ্বারা প্রস্তাবিত।

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


7
এটি সংকলন করে না, ইভেন্টহ্যান্ডলারটি কেবল + = বা - = এর বাম দিকে থাকতে পারে।
কোডআরডিক

2
আরও ব্যাখ্যা প্রদানের পরে ভোট সরানো। এসকিউএল রাষ্ট্রটি এখানে পুরো ধারণাটিকে বেশ ধ্বংস করছে ... :(
কোড্রেডিক

1
ধন্যবাদ ব্লেয়ার এবং এসও অনুসন্ধান, আমি যা খুঁজছিলাম ঠিক (বিরক্তিকর আপনি যদিও এটি ক্লাসের বাইরে করতে পারবেন না)
জর্জ মাউয়ার

3
সমতা জন্য প্রতিনিধিদের তুলনা করার সময় বেশিরভাগ সময় সমস্যা দেখা দেয়। সুতরাং Delegate.Equals(objA, objB)আপনি যদি একই ডেলিগেটের উপস্থিতি পরীক্ষা করতে চান তবে ব্যবহার করুন use অন্যথায় বৈশিষ্ট্য পৃথকভাবে পছন্দ করুন if(objA.Method.Name == objB.Method.Name && objA.Target.GetType().FullName == objB.Target.GetType().FullName)
সঞ্জয়

2
এই কোডটি কোনও উইনফোর্মে কাজ করছে না। এটি কি কঠোরভাবে এএসপি.নেটের জন্য?
jp2code

211

আমি সম্প্রতি একইরকম পরিস্থিতিতে পৌঁছেছি যেখানে একটি ইভেন্টের জন্য আমাকে কেবল একবার হ্যান্ডলার নিবন্ধিত করতে হবে। আমি দেখেছি যে আপনি প্রথমে নিরাপদে নিবন্ধন করতে পারবেন এবং হ্যান্ডলারটি নিবন্ধিত না থাকলেও আবার নিবন্ধভুক্ত করতে পারেন:

myClass.MyEvent -= MyHandler;
myClass.MyEvent += MyHandler;

নোট করুন যে প্রতিবার আপনি আপনার হ্যান্ডলারটি নিবন্ধভুক্ত করবেন তা নিশ্চিত করবে যে আপনার হ্যান্ডলারটি একবারে নিবন্ধিত হয়েছে। আমার কাছে বেশ ভালো অনুশীলনের মতো মনে হচ্ছে :)


9
ঝুঁকিপূর্ণ বলে মনে হচ্ছে; কোনও ইভেন্ট হ্যান্ডলারটি সরিয়ে দেওয়ার পরে এবং এটি আবার যুক্ত করার আগে গুলি চালানো হলে তা মিস হয়ে যাবে।
জিমি

27
অবশ্যই। আপনার মানে এটি থ্রেড নিরাপদ নয়। তবে একমাত্র একাধিক থ্রেড বা এ জাতীয় চলমান চলাকালীন সমস্যা হতে পারে যা স্বাভাবিক নয়। বেশিরভাগ ক্ষেত্রে সরলতার জন্য এটি যথেষ্ট ভাল হওয়া উচিত।
alf

6
এটা আমাকে বিরক্ত করে। কেবলমাত্র আপনি বর্তমানে আপনার কোডটিতে সুস্পষ্টভাবে থ্রেড তৈরি করছেন না এর অর্থ এই নয় যে একাধিক থ্রেড নেই, বা সেগুলি পরে যুক্ত করা হবে না। যত তাড়াতাড়ি আপনি (বা দলে থাকা অন্য কেউ, সম্ভবত কয়েক মাস পরে) কোনও কর্মী থ্রেড যুক্ত করুন বা ইউআই এবং নেটওয়ার্ক সংযোগ উভয়কেই সাড়া দিন, এটি অত্যন্ত বিরতিযুক্ত বাদ পড়া ইভেন্টের দরজা উন্মুক্ত করে।
টেকনোফিল 14'15

1
আমি বিশ্বাস করি যে অপসারণ এবং আবার যোগ করার মধ্যে সময়ের উইন্ডোটি এত ছোট, এটি মিস হওয়া ইভেন্টগুলির খুব সম্ভবত সম্ভাবনা নেই তবে হ্যাঁ, এটি এখনও সম্ভব।
অ্যালিসন

2
আপনি যদি এটি কোনও ইউআই ইত্যাদি আপডেট করার মতো ব্যবহার করে থাকেন তবে এর যেমন তুচ্ছ কাজ এটি ঝুঁকি ঠিক। এটি যদি নেটওয়ার্ক প্যাকেট হ্যান্ডলিং ইত্যাদির জন্য হয় তবে আমি এটি ব্যবহার করব না।
রোলগুলি

18

এটি যদি কেবলমাত্র হ্যান্ডলার হয় তবে আপনি ইভেন্টটি নাল কিনা তা পরীক্ষা করে দেখতে পারেন, যদি তা না হয় তবে হ্যান্ডলারটি যুক্ত করা হয়েছে।

আমি মনে করি আপনি নিজের হ্যান্ডলারের সাথে ইভেন্টটি নিরাপদে কল করতে পারেন - এটি যোগ না করা সত্ত্বেও (যদি না হয় তবে আপনি এটি ধরতে পারতেন) - যোগ করার আগে এটি সেখানে নেই বলে নিশ্চিত করে নিন।


3
ইভেন্টটি অন্য কোথাও পরিচালনা করার সাথে সাথে এই যুক্তিটি ভেঙে যাবে।
বুগদ্বীপ 87

6

এই উদাহরণটি দেখায় যে কীভাবে যোগ করা সমস্ত হ্যান্ডলারের প্রতিনিধিদের পুনরুদ্ধার করতে getInvocationList () পদ্ধতিটি ব্যবহার করতে হয়। যদি আপনি কোনও সুনির্দিষ্ট হ্যান্ডলার (ফাংশন) যুক্ত করা হয়েছে কিনা তা সন্ধান করছেন তবে আপনি অ্যারে ব্যবহার করতে পারেন।

public class MyClass
{
  event Action MyEvent;
}

...

MyClass myClass = new MyClass();
myClass.MyEvent += SomeFunction;

...

Action[] handlers = myClass.MyEvent.GetInvocationList(); //this will be an array of 1 in this example

Console.WriteLine(handlers[0].Method.Name);//prints the name of the method

কোনও নির্দিষ্ট ফাংশন যুক্ত হয়েছে কিনা তা দেখতে আপনি প্রতিনিধিটির পদ্ধতি সম্পত্তিতে বিভিন্ন সম্পত্তি পরীক্ষা করতে পারেন।

আপনি যদি কেবল একটি সংযুক্ত আছে কিনা তা সন্ধান করছেন তবে আপনি কেবল শূন্যের জন্য পরীক্ষা করতে পারেন।


GetInvocationList () আমার শ্রেণীর সদস্য নয়। আসলে, আমি যে কোনও অবজেক্ট বা হ্যান্ডলারের অ্যাক্সেস পেয়েছি আমি এই পদ্ধতিটি খুঁজে পেতে পারি না ...
কোডআরডিক

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

4

আমি যদি আপনার সমস্যাটি সঠিকভাবে বুঝতে পারি তবে আপনার কাছে আরও বড় সমস্যা হতে পারে। আপনি বলেছিলেন যে অন্যান্য বস্তুগুলি এই ইভেন্টগুলিতে সদস্যতা নিতে পারে। যখন বস্তুটি সিরিয়ালাইজ করা হয় এবং অন্যান্য বস্তুগুলি ডিসরিয়ালাইজ করা হয় (আপনি যেগুলির নিয়ন্ত্রণ করেন না) তাদের ইভেন্ট হ্যান্ডলারগুলি হারাবে।

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


1
ডি আহা! এমনকি এটি ভাবিনিও ... যদিও আমার আসল সমস্যাটি বিবেচনা করে স্পষ্ট হওয়া উচিত ছিল আমার নিজের হ্যান্ডলারটি হারিয়ে যাওয়া।
কোডরেডিক

2

আমার পক্ষে কাজ করার একমাত্র উপায়টি হল বুলিয়ান ভেরিয়েবল তৈরি করা যা আমি ইভেন্টটি যুক্ত করার সময় সত্য হিসাবে সেট করেছিলাম। তারপরে আমি জিজ্ঞাসা করি: ভেরিয়েবলটি মিথ্যা হলে আমি ইভেন্টটি যুক্ত করি add

bool alreadyAdded = false;

এই পরিবর্তনশীল গ্লোবাল হতে পারে।

if(!alreadyAdded)
{
    myClass.MyEvent += MyHandler;
    alreadyAdded = true;
}

1

আমি আলফের উত্তরের সাথে একমত, তবে এতে সামান্য পরিবর্তন হ'ল, ব্যবহার করা,

           try
            {
                control_name.Click -= event_Click;
                main_browser.Document.Click += Document_Click;
            }
            catch(Exception exce)
            {
                main_browser.Document.Click += Document_Click;
            }

0
EventHandler.GetInvocationList().Length > 0

2
তালিকাটি == নাল হয়ে গেলে কি এটি ছুঁড়ে না?
বোরিস কলেনস

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