.NET- এ ইভেন্ট স্বাক্ষর - একটি শক্ত টাইপযুক্ত 'প্রেরক' ব্যবহার করছেন?


106

আমি পুরোপুরি বুঝতে পারি যে আমি যা প্রস্তাব করছি তা। নেট নির্দেশিকা অনুসরণ করে না, এবং তাই কেবল এই কারণেই সম্ভবত একটি দুর্বল ধারণা। তবে, আমি এটি দুটি সম্ভাব্য দৃষ্টিকোণ থেকে বিবেচনা করতে চাই:

(1) আমার নিজের উন্নয়ন কাজের জন্য এটি ব্যবহার করার বিষয়টি বিবেচনা করা উচিত, যা অভ্যন্তরীণ উদ্দেশ্যে 100%।

(২) এটি কী এমন ধারণা যা ফ্রেমওয়ার্ক ডিজাইনাররা পরিবর্তন বা আপডেটের বিষয়ে বিবেচনা করতে পারে?

আমি এমন ইভেন্টের স্বাক্ষরটি ব্যবহার করার বিষয়ে ভাবছি যা এটি 'অবজেক্ট' হিসাবে টাইপ না করে একটি শক্ত টাইপযুক্ত 'প্রেরক' ব্যবহার করে যা বর্তমান। নেট নকশার প্যাটার্ন। এটি হ'ল কোনও স্ট্যান্ডার্ড ইভেন্টের স্বাক্ষর ব্যবহারের পরিবর্তে এটি দেখতে লাগে:

class Publisher
{
    public event EventHandler<PublisherEventArgs> SomeEvent;
}

আমি এমন ইভেন্টের স্বাক্ষর ব্যবহার করার বিষয়ে বিবেচনা করছি যা শক্তিশালী টাইপযুক্ত 'প্রেরক' পরামিতিটি ব্যবহার করে:

প্রথমে একটি "স্ট্রং টাইপড এভেন্টহ্যান্ডলার" সংজ্ঞা দিন:

[SerializableAttribute]
public delegate void StrongTypedEventHandler<TSender, TEventArgs>(
    TSender sender,
    TEventArgs e
)
where TEventArgs : EventArgs;

এটি একটি অ্যাকশন <টিসেন্ডার, টিভেন্টআরগস> এর থেকে আলাদা নয়, তবে এর ব্যবহার করে StrongTypedEventHandlerআমরা প্রয়োগ করি যে টিভেন্টআর্গগুলি থেকে প্রাপ্ত System.EventArgs

এর পরে, উদাহরণ হিসাবে, আমরা স্ট্রং টাইপড এভেন্টহ্যান্ডলারটি একটি প্রকাশনা শ্রেণিতে নিম্নরূপ ব্যবহার করতে পারি:

class Publisher
{
    public event StrongTypedEventHandler<Publisher, PublisherEventArgs> SomeEvent;

    protected void OnSomeEvent()
    {
        if (SomeEvent != null)
        {
            SomeEvent(this, new PublisherEventArgs(...));
        }
    }
}

উপরের ব্যবস্থা গ্রাহকগণকে শক্তিশালী-টাইপ ইভেন্ট হ্যান্ডলারটি ব্যবহার করতে সক্ষম করবে যার জন্য কাস্টিংয়ের প্রয়োজন নেই:

class Subscriber
{
    void SomeEventHandler(Publisher sender, PublisherEventArgs e)
    {           
        if (sender.Name == "John Smith")
        {
            // ...
        }
    }
}

আমি পুরোপুরি বুঝতে পারি যে এটি স্ট্যান্ডার্ড .NET ইভেন্ট-হ্যান্ডলিং প্যাটার্নের সাথে ভেঙে গেছে; তবে, মনে রাখবেন যে বৈপরীত্য কোনও গ্রাহককে যদি ইচ্ছা হয় তবে একটি traditionalতিহ্যবাহী ইভেন্ট হ্যান্ডলিং স্বাক্ষর ব্যবহার করতে সক্ষম করে:

class Subscriber
{
    void SomeEventHandler(object sender, PublisherEventArgs e)
    {           
        if (((Publisher)sender).Name == "John Smith")
        {
            // ...
        }
    }
}

এটি হ'ল, যদি কোনও ইভেন্ট হ্যান্ডলারের অবিচ্ছিন্ন (বা সম্ভবত অজানা) অবজেক্টের ধরণের ইভেন্টগুলিতে সাবস্ক্রাইব করার প্রয়োজন হয়, হ্যান্ডলারটি 'প্রেরক' পরামিতিটি 'অবজেক্ট' হিসাবে টাইপ করতে পারে যাতে সম্ভাব্য প্রেরক সামগ্রীর পূর্ণ প্রশস্ততা পরিচালনা করতে পারে।

কনভেনশন ভাঙা ব্যতীত (যা এমন কিছু যা আমি হালকাভাবে নিই না, বিশ্বাস করুন) আমি এটার কোনও উত্থানের কথা ভাবতে পারি না।

এখানে কিছু সিএলএস সম্মতি সংক্রান্ত সমস্যা থাকতে পারে। এটি ভিজ্যুয়াল বেসিক। নেট ২০০ 100% জরিমানা (আমি পরীক্ষা করেছি) এ চলে, তবে আমি বিশ্বাস করি যে ভিজ্যুয়াল বেসিক .NET এর পুরানো সংস্করণগুলি 2005 এর মধ্যবর্তী সময়ে প্রতিনিধিদের সাম্প্রদায়িকতা এবং বিপরীতে নেই। [সম্পাদনা করুন: আমি এর পর থেকে এটি পরীক্ষা করেছি এবং এটি নিশ্চিত হয়ে গেছে: ভিবি.এনইটি 2005 এবং নীচে এটি পরিচালনা করতে পারে না, তবে ভিবি.এনইট ২০০৮ 100% জরিমানা। নীচে "সম্পাদনা # 2" দেখুন]] এখানে অন্যান্যও থাকতে পারে N নেট ভাষাতেও এর সাথে সমস্যা রয়েছে I আমি নিশ্চিত হতে পারি না।

তবে আমি নিজেকে সি # বা ভিজ্যুয়াল বেসিক। নেট ছাড়া অন্য কোনও ভাষার জন্য বিকাশ করতে দেখছি না এবং নেট। ফ্রেমওয়ার্ক 3.0 এবং তারপরের জন্য এটি সি # এবং ভিবি.এনইটি-তে সীমাবদ্ধ রাখতে আমার কোনও আপত্তি নেই। (আমি এই মুহুর্তে 2.0 তে ফিরে যেতে ভাবতে পারি না, সত্যি বলতে।)

অন্য কেউ এই সমস্যা নিয়ে ভাবতে পারেন? অথবা এটি কেবল কনভেনশনটির সাথে এতটা ভেঙে যায় যে এটি মানুষের পেটে মোড় ঘুরিয়ে দেয়?

এখানে কিছু সম্পর্কিত লিঙ্ক পাওয়া গেছে যা আমি পেয়েছি:

(1) ইভেন্ট ডিজাইনের গাইডলাইন [এমএসডিএন 3.5]

(২) সি # সাধারণ ইভেন্ট উত্থাপন - "প্রেরক" বনাম কাস্টম ইভেন্টআরগস [স্ট্যাকওভারফ্লো ২০০৯] ব্যবহার করে

(3) নেট মধ্যে ইভেন্ট স্বাক্ষর নিদর্শন [স্ট্যাকওভারফ্লো ২০০৮]

আমি এই বিষয়ে কারও এবং সবার মতামতে আগ্রহী ...

আগাম ধন্যবাদ,

মাইক

সম্পাদনা # 1: এটি টমি কারিয়ারের পোস্টের প্রতিক্রিয়াতে :

এখানে একটি পরিপূর্ণ কাজের উদাহরণ যা দেখায় যে দৃ strong়-টাইপযুক্ত ইভেন্ট হ্যান্ডলার এবং বর্তমান স্ট্যান্ডার্ড ইভেন্ট হ্যান্ডলার যারা 'অবজেক্ট প্রেরক' পরামিতি ব্যবহার করে তারা এই পদ্ধতির সাথে সহাবস্থান করতে পারে। আপনি কোডটিতে কপি-পেস্ট করতে পারেন এবং এটিকে রান দিতে পারেন:

namespace csScrap.GenericEventHandling
{
    class PublisherEventArgs : EventArgs
    {
        // ...
    }

    [SerializableAttribute]
    public delegate void StrongTypedEventHandler<TSender, TEventArgs>(
        TSender sender,
        TEventArgs e
    )
    where TEventArgs : EventArgs;

    class Publisher
    {
        public event StrongTypedEventHandler<Publisher, PublisherEventArgs> SomeEvent;

        public void OnSomeEvent()
        {
            if (SomeEvent != null)
            {
                SomeEvent(this, new PublisherEventArgs());
            }
        }
    }

    class StrongTypedSubscriber
    {
        public void SomeEventHandler(Publisher sender, PublisherEventArgs e)
        {
            MessageBox.Show("StrongTypedSubscriber.SomeEventHandler called.");
        }
    }

    class TraditionalSubscriber
    {
        public void SomeEventHandler(object sender, PublisherEventArgs e)
        {
            MessageBox.Show("TraditionalSubscriber.SomeEventHandler called.");
        }
    }

    class Tester
    {
        public static void Main()
        {
            Publisher publisher = new Publisher();

            StrongTypedSubscriber strongTypedSubscriber = new StrongTypedSubscriber();
            TraditionalSubscriber traditionalSubscriber = new TraditionalSubscriber();

            publisher.SomeEvent += strongTypedSubscriber.SomeEventHandler;
            publisher.SomeEvent += traditionalSubscriber.SomeEventHandler;

            publisher.OnSomeEvent();
        }
    }
}

সম্পাদনা # 2: এটি অবিশ্বাস্যতা এবং স্ববিরোধিতা এবং এটি এখানে কীভাবে প্রযোজ্য তা সম্পর্কিত অ্যান্ড্রু হেরের বক্তব্যের প্রতিক্রিয়া হিসাবে । সি # ভাষার প্রতিনিধিদের এত দীর্ঘকাল ধরে সহজাততা এবং বৈপরীত্য ছিল যে এটি কেবল "অন্তর্নিহিত" বোধ করে, তবে তা নয়। এটি এমন কিছু হতে পারে যা সিএলআরে সক্ষম হয়েছে, আমি জানি না, তবে ভিজ্যুয়াল বেসিক। নেট তার প্রতিনিধিদের জন্য .NET ফ্রেমওয়ার্ক 3.0 (VB.NET ২০০৮) অবধি সাম্প্রদায়িকতা এবং বৈপরীত্যের সক্ষমতা পায়নি। এবং ফলস্বরূপ, .NET 2.0 এবং এর নীচে ভিজ্যুয়াল বেসিক.এনইটি এই পদ্ধতির ব্যবহার করতে সক্ষম হবে না।

উদাহরণস্বরূপ, উপরোক্ত উদাহরণটি VB.NET এ নিম্নলিখিত হিসাবে অনুবাদ করা যেতে পারে:

Namespace GenericEventHandling
    Class PublisherEventArgs
        Inherits EventArgs
        ' ...
        ' ...
    End Class

    <SerializableAttribute()> _
    Public Delegate Sub StrongTypedEventHandler(Of TSender, TEventArgs As EventArgs) _
        (ByVal sender As TSender, ByVal e As TEventArgs)

    Class Publisher
        Public Event SomeEvent As StrongTypedEventHandler(Of Publisher, PublisherEventArgs)

        Public Sub OnSomeEvent()
            RaiseEvent SomeEvent(Me, New PublisherEventArgs)
        End Sub
    End Class

    Class StrongTypedSubscriber
        Public Sub SomeEventHandler(ByVal sender As Publisher, ByVal e As PublisherEventArgs)
            MessageBox.Show("StrongTypedSubscriber.SomeEventHandler called.")
        End Sub
    End Class

    Class TraditionalSubscriber
        Public Sub SomeEventHandler(ByVal sender As Object, ByVal e As PublisherEventArgs)
            MessageBox.Show("TraditionalSubscriber.SomeEventHandler called.")
        End Sub
    End Class

    Class Tester
        Public Shared Sub Main()
            Dim publisher As Publisher = New Publisher

            Dim strongTypedSubscriber As StrongTypedSubscriber = New StrongTypedSubscriber
            Dim traditionalSubscriber As TraditionalSubscriber = New TraditionalSubscriber

            AddHandler publisher.SomeEvent, AddressOf strongTypedSubscriber.SomeEventHandler
            AddHandler publisher.SomeEvent, AddressOf traditionalSubscriber.SomeEventHandler

            publisher.OnSomeEvent()
        End Sub
    End Class
End Namespace

VB.NET 2008 এটি 100% জরিমানা চালাতে পারে। তবে আমি এখন এটি VB.NET 2005 এ পরীক্ষা করেছি, নিশ্চিত হওয়ার জন্য, এবং এটি সংকলন করে না, উল্লেখ করে:

পদ্ধতি 'পাবলিক সাব সোমেনভেস্ট হ্যান্ডলার (অবজেক্ট হিসাবে প্রেরক, এবং হিসাবে vbGenericEventHandling.GenericEventHandling.PublisherEventArgs)' এর প্রতিনিধি হিসাবে একই স্বাক্ষর নেই 'ডেলিগেট সাব স্ট্রংটাইপড এভেন্টহ্যান্ডারস প্রকাশক হিসাবে প্রকাশক (টেলিগ্রাহক হিসাবে টেনট্রেজারস হিসাবে)। '

মূলত, প্রতিনিধিরা VB.NET সংস্করণ 2005 এবং এর নীচে নীচে আক্রমণ করে। আমি আসলে কয়েক বছর আগে এই ধারণাটি ভেবেছিলাম, কিন্তু ভিবি.এনইটি এর সাথে এটি মোকাবেলা করতে অক্ষমতা আমাকে বিরক্ত করেছিল ... তবে আমি এখন সি # তে দৃly়ভাবে চলে এসেছি, এবং ভিবি.এনইটি এখন এটি পরিচালনা করতে পারে, তাই, ভাল, তাই এই পোস্ট

সম্পাদনা করুন: আপডেট # 3

ঠিক আছে, আমি এটি বেশ কিছু সময়ের জন্য বেশ সফলভাবে ব্যবহার করে আসছি। এটি সত্যিই একটি দুর্দান্ত সিস্টেম। আমি আমার "স্ট্রংটাইপড এভেন্টহ্যান্ডলার" নামটি "জেনেরিকসেন্টহ্যান্ডলার" হিসাবে নামকরণ করার সিদ্ধান্ত নিয়েছি, নীচে বর্ণিত:

[SerializableAttribute]
public delegate void GenericEventHandler<TSender, TEventArgs>(
    TSender sender,
    TEventArgs e
)
where TEventArgs : EventArgs;

এই নামকরণের পরিবর্তে, আমি উপরে বর্ণিত হিসাবে ঠিক এটি প্রয়োগ করেছি।

এটি FxCop বিধি CA1009 এর উপর দিয়ে ট্রিপ করে, যা বলে:

"কনভেনশন অনুসারে। নেট ইভেন্টের দুটি পরামিতি রয়েছে যা ইভেন্ট প্রেরক এবং ইভেন্টের ডেটা নির্দিষ্ট করে Event ইভেন্ট হ্যান্ডলার স্বাক্ষরগুলি এই ফর্মটি অনুসরণ করা উচিত: অকার্যকর মাইভেন্টহ্যান্ডলার (অবজেক্ট প্রেরক, ইভেন্টআর্গস ই) The 'প্রেরক' পরামিতি সর্বদা সিস্টেমের হয় O অবজেক্ট, এমনকি যদি আরও নির্দিষ্ট ধরণের নিয়োগ করা সম্ভব হয় তবে 'ই' প্যারামিটার সর্বদা System.EventArgs টাইপ থাকে ts ইভেন্টগুলির ডেটা সরবরাহ করে না এমন ইভেন্টগুলি সিস্টেম.এভেন্টহ্যান্ডলার প্রতিনিধি প্রকারটি ব্যবহার করা উচিত Event ইভেন্ট হ্যান্ডলারের শূন্যতা ফিরে আসে যাতে তারা প্রেরণ করতে পারে প্রতিটি ইভেন্ট একাধিক টার্গেট পদ্ধতিতে। কোনও লক্ষ্য দ্বারা প্রত্যাবর্তিত কোনও মানই প্রথম কলের পরে হারিয়ে যাবে ""

অবশ্যই, আমরা এগুলি সব জানি এবং যাইহোক নিয়মগুলি ভঙ্গ করছি। (সমস্ত ইভেন্ট হ্যান্ডলাররা কোনও ক্ষেত্রে পছন্দসই হলে তাদের স্বাক্ষরে স্ট্যান্ডার্ড 'অবজেক্ট প্রেরক' ব্যবহার করতে পারেন - এটি একটি অ-ব্রেকিং পরিবর্তন))

সুতরাং একটি ব্যবহার SuppressMessageAttributeকৌশলটি করে:

[SuppressMessage("Microsoft.Design", "CA1009:DeclareEventHandlersCorrectly",
    Justification = "Using strong-typed GenericEventHandler<TSender, TEventArgs> event handler pattern.")]

আমি আশা করি এই পদ্ধতির ভবিষ্যতে কোনও এক সময় প্রমিত হয়ে উঠবে। এটি সত্যিই খুব সুন্দরভাবে কাজ করে।

আপনার সকল মতামত বলার জন্য ধন্যবাদ, আমি সত্যিই এটি প্রশংসা ...

মাইক


6
এটা কর. (এটি কোনও উত্তরকে ন্যায়সঙ্গত বলে মনে করেন না))
কনরাড রুডলফ

1
আমার যুক্তিগুলি সত্যই আপনাকে দেখানো হয়নি: অবশ্যই আপনার নিজের প্রকল্পে এটি করা উচিত। কেন ছাত্রলীগে এটি কাজ করবে না তা তাদের যুক্তি ছিল।
টমি কারিয়ার

3
ম্যান, আমার ইচ্ছা যদি আমার প্রকল্পটি এই কাজটি শুরু থেকেই করত তবে আমি প্রেরককে কাস্ট করা ঘৃণা করি।
ম্যাট এইচ

7
এখন এই একটি প্রশ্ন। লোকেরা, দেখুন? এই টুইট-আকারের oh hi this my hom work solve it plz :code dump:প্রশ্নগুলির মধ্যে একটি নয় , তবে আমরা একটি প্রশ্ন থেকে শিখি
ক্যামিলো মার্টিন

3
আরেকটি পরামর্শ, শুধু এটির EventHandler<,>চেয়ে নাম দিন GenericEventHandler<,>EventHandler<>বিসিএলে ইতিমধ্যে জেনেরিক রয়েছে যার নাম দেওয়া হয়েছে কেবল ইভেন্টহ্যান্ডলার। সুতরাং ইভেন্টহ্যান্ডলারটি একটি সাধারণ নাম এবং প্রতিনিধিরা প্রকারের ওভারলোডগুলি সমর্থন করে
নওফাল

উত্তর:


25

মনে হচ্ছে মাইক্রোসফ্ট এটিকে বেছে নিয়েছে কারণ এমএসডিএন-তে একই উদাহরণ রয়েছে:

জেনেরিক প্রতিনিধিরা


2
+1 আহ, দুর্দান্ত। তারা সত্যই এটি গ্রহণ করেছে। এটা ভাল. আমি আশা করি, যদিও তারা ভিএস আইডিই-র মধ্যে এটি একটি স্বীকৃত প্যাটার্ন তৈরি করেছে, কারণ এখনকার মতো, ইন্টেলিসেন্স ইত্যাদির ক্ষেত্রে এই প্যাটার্নটি ব্যবহার করা আরও বিশ্রী
মাইক রোজেনব্লাম

13

আপনি যা প্রস্তাব করছেন তা আসলে প্রচুর পরিমাণে জ্ঞান তৈরি করে, এবং আমি কেবল অবাক করে দেখি যে এটি কেবল সেইভাবেই এটির কারণ কারণ এটি মূলত জেনারিকদের আগে তৈরি করা হয়েছিল, বা এর যদি সত্যিকারের কারণ রয়েছে।


1
আমি নিশ্চিত যে এটি ঠিক কারণ। তবে, এখন যেহেতু ভাষার নতুন সংস্করণগুলি এটিকে পরিচালনা করতে পারে তার বিপরীতে, দেখে মনে হচ্ছে তাদের এটি পিছনের দিকে সামঞ্জস্যপূর্ণ পদ্ধতিতে পরিচালনা করতে সক্ষম হওয়া উচিত। 'প্রেরক অবজেক্ট' ব্যবহার করে এমন পূর্ববর্তী হ্যান্ডলারগুলি ভাঙবে না। তবে এটি পুরানো ভাষার ক্ষেত্রে সত্য নয় এবং কিছু বর্তমান .NET ভাষার ক্ষেত্রেও এটি সত্য নয় I'm
মাইক রোজেনব্লুম

13

উইন্ডোজ রানটাইম (উইনআরটি) একটি TypedEventHandler<TSender, TResult>প্রতিনিধিকে পরিচয় করিয়ে দেয়, যা আপনার কাজটি ঠিক তাই StrongTypedEventHandler<TSender, TResult>করে তবে TResultপ্রকারের প্যারামিটারের সীমাবদ্ধতা ছাড়াই :

public delegate void TypedEventHandler<TSender, TResult>(TSender sender,
                                                         TResult args);

এমএসডিএন ডকুমেন্টেশন এখানে


1
আহ, দেখে শুনে ভাল হয়েছে যে অগ্রগতি আছে ... আমি অবাক হয়েছি কেন কেন ট্র্যাসল্টকে 'ইভেন্টআর্গস' শ্রেণীর উত্তরাধিকার সূত্রে সীমাবদ্ধ করা হয়নি। 'ইভেন্টআর্গস' বেস শ্রেণিটি মূলত খালি; তারা এই সীমাবদ্ধতা থেকে দূরে সরে যেতে পারে?
মাইক রোজেনব্লুম

এটি নকশা দল থেকে একটি তদারকি হতে পারে; কে জানে.
পিয়েরে আরনাড

ভাল, ইভেন্টগুলি ব্যবহার না করেই দুর্দান্ত কাজ করে EventArgs, এটি কেবল একটি সম্মেলনের জিনিস
সেবাস্টিয়ান

3
এটা বিশেষভাবে TypedEventHandler ডকুমেন্টেশনে যে argsহতে হবে nullযদি কোন ইভেন্ট ডেটা, তাই এটি প্রদর্শিত হচ্ছে না যে, তারা ডিফল্ট ভাবে একটি মূলত খালি বস্তুর ব্যবহার থেকে দূরে পাচ্ছেন। আমি অনুমান করছি যে আসল ধারণাটি ছিল যে দ্বিতীয় পরামিতি জাতীয় কোনও পদ্ধতি হ'ল EventArgsকোনও অনুষ্ঠান পরিচালনা করতে পারে কারণ প্রকারগুলি সর্বদা উপযুক্ত। তারা সম্ভবত এখন উপলব্ধি করছে যে একটি পদ্ধতিতে একাধিক বিভিন্ন ইভেন্ট পরিচালনা করতে সক্ষম হওয়া এতটা গুরুত্বপূর্ণ নয়।
jmcilhinney

1
এটি কোনও তদারকের মতো দেখায় না। প্রতিবন্ধকতাটি সিস্টেম থেকে সরিয়ে দেওয়া হয়েছিল ventএইভেনথ হ্যান্ডলার <TEventArgs> প্রতিনিধিও। রেফারেন্সসোর্স.মাইক্রোসফট.কম
#mscorlib

5

আমি নিম্নলিখিত বিবৃতি দিয়ে ইস্যু গ্রহণ:

  • আমি বিশ্বাস করি যে ভিজ্যুয়াল বেসিক .NET এর পুরানো সংস্করণগুলি 2005 এর মধ্যে ডেলিগেট covariance এবং বৈপরীত্য নেই।
  • আমি সম্পূর্ণরূপে উপলব্ধি করতে পারি যে এটি নিন্দার বিরুদ্ধে।

প্রথমত, আপনি এখানে যা কিছু করেছেন তা সর্বজনগ্রাহ্য বা বৈপরীত্যের সাথে কিছু করার নেই। ( সম্পাদনা করুন: পূর্ববর্তী বিবৃতিটি ভুল, অধিক তথ্যের জন্য দয়া করে প্রতিনিধিদের মধ্যে কোভারিয়েন্স এবং কনট্র্যাভারিয়েন্স দেখুন ) এই সমাধানটি সমস্ত সিএলআর সংস্করণ ২.০ এবং এর ঠিক ঠিক কাজ করবে (স্পষ্টতই এটি জেনারিকগুলি ব্যবহার করার কারণে কোনও সিএলআর 1.0 অ্যাপ্লিকেশনটিতে কাজ করবে না )।

দ্বিতীয়ত, আমি দৃ strongly়ভাবে দ্বিমত পোষণ করছি যে আপনার ধারণা "নিন্দা" এর উপর নির্ভর করে কারণ এটি একটি দুর্দান্ত ধারণা।


2
হাই অ্যান্ড্রু, থাম্ব আপ আপ জন্য ধন্যবাদ! আপনার খ্যাতি স্তর বিবেচনা করে, এটি সত্যই আমার কাছে অনেক অর্থ ... সমবায়তা / বিপরীতে ইস্যুতে: যদি গ্রাহক দ্বারা সরবরাহ করা প্রতিনিধি প্রকাশকের ইভেন্টের স্বাক্ষরের সাথে ঠিক মেলে না, তবে স্বনির্ভরতা এবং বৈপরীত্য জড়িত। সি # এর চিরকাল থেকেই প্রতিনিধি সম্প্রদায় এবং বৈপরীত্য ছিল, তাই এটি স্বতন্ত্র অনুভূত হয় তবে VB.NET .NET 3.0 পর্যন্ত প্রতিনিধিদের সমবায়তা এবং বিপরীতমুখীতা পায় নি। সুতরাং, .NET 2.0 এবং এর নীচে VB.NET এই সিস্টেমটি ব্যবহার করতে সক্ষম হবে না। (উপরে "সম্পাদনা # 2" এ যুক্ত কোড উদাহরণটি দেখুন See)
মাইক রোজেনব্লুম

@ মাইক - আমার ক্ষমা, আপনি 100% সঠিক! আপনার উত্তরটি প্রতিবিম্বিত করতে আমি আমার উত্তর সম্পাদনা করেছি :)
অ্যান্ড্রু হার

4
আহ, আকর্ষণীয়! দেখে মনে হচ্ছে প্রতিনিধি কোভেরিয়েন্স / বৈপরীত্য সিএলআরের অংশ, তবে (কারণ আমি জানি না) এটি সাম্প্রতিক সংস্করণের আগে ভিবি.এনইটি দ্বারা প্রকাশ করা হয়নি। এখানে ফ্রেঞ্চেস্কো বালেনার একটি নিবন্ধ এখানে দেখায় যে কীভাবে প্রতিনিধিত্বমূলক বৈকল্পিক প্রতিচ্ছবি ব্যবহার করে কীভাবে ভাষা দ্বারা সক্ষম না করা হয় তা অর্জন করতে পারে: ডটনেট 2 টেমেক্স / ব্লগস / ফেবালেনা /…
মাইক রোজেনব্লুম

1
@ মাইক - সিএলআর এখনও সমর্থন করে এমন জিনিসগুলি শিখতে আগ্রহী yet
অ্যান্ড্রু হার

5

এটি কীভাবে নতুন উইনআরটি-র সাথে পরিচালনা করা হয়েছিল এবং এখানে অন্যান্য মতামতের উপর ভিত্তি করে দেখেছিলাম এবং অবশেষে এটি করার মতো করে স্থির হয়েছি:

[Serializable]
public delegate void TypedEventHandler<in TSender, in TEventArgs>(
    TSender sender,
    TEventArgs e
) where TEventArgs : EventArgs;

উইনআরটিতে টাইপডেভেন্টহ্যান্ডলার নামটি বিবেচনা করে এটি এগিয়ে যাওয়ার সেরা উপায় বলে মনে হয়।


TEventArgs এ জেনেরিক বাধা কেন যুক্ত করবেন? এটি ইভেন্টহ্যান্ডলার <> এবং টাইপডেভেন্টহ্যান্ডলার <,> থেকে সরানো হয়েছে কারণ এটি সত্যিকার অর্থে তৈরি হয়নি।
মাইক মেরিনোভস্কি

2

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


আপনি হয়ত ঠিক বলেছেন ... অন্যদিকে, আমি মনে করি এটি কেবল একটি "স্ট্যান্ডার্ড", এবং সম্ভবত কোনও প্রযুক্তিগত সমস্যা নয়। এটি হ'ল, এই সামর্থ্যটি সমস্ত বর্তমান। নেট ভাষায় উপস্থিত থাকতে পারে, আমি জানি না। আমি জানি যে C # এবং VB.NET এটি পরিচালনা করতে পারে। যাইহোক, আমি নিশ্চিত নই যে এটি সমস্ত বর্তমান .NET ভাষায় কীভাবে বিস্তৃতভাবে কাজ করে ... তবে যেহেতু এটি সি # এবং ভিবি.এনইটি তে কাজ করে এবং এখানকার প্রত্যেকেই এতটা সহায়ক, তাই আমি মনে করি আমি এটি করার সম্ভাবনা খুব বেশি। :-)
মাইক রোজেনব্লুম

2

আমি যা বুঝতে পারি তা থেকে, "প্রেরক" ক্ষেত্রটি সর্বদা ইভেন্টটির সাবস্ক্রিপশন ধারণ করে এমন অবজেক্টের উল্লেখ করা উচিত। আমার কাছে যদি আমার ড্রথার থাকে, তবে একটি ক্ষেত্রের হোল্ডিংয়ের তথ্যও একটি ইভেন্টের সদস্যতার জন্য যথেষ্ট হবে যদি এটি প্রয়োজনীয় হয়ে যায় (*) (উদাহরণস্বরূপ, একটি পরিবর্তন-লগার যা 'সংগ্রহ-পরিবর্তিত' ইভেন্টগুলিতে সাবস্ক্রাইব করে; এতে দুটি অংশ রয়েছে) যার মধ্যে একটি আসল কাজ করে এবং প্রকৃত ডেটা ধারণ করে এবং অন্যটি পাবলিক ইন্টারফেসের মোড়ক সরবরাহ করে, প্রধান অংশটি মোড়কের অংশটির একটি দুর্বল রেফারেন্স রাখতে পারে If যদি মোড়কের অংশটি আবর্জনা সংগ্রহ করে, তার অর্থ হবে যে তথ্য সংগ্রহ করা হচ্ছে তাতে আর কেউ আগ্রহী ছিল না, এবং পরিবর্তন-লগারের পক্ষে এটি প্রাপ্ত যে কোনও ইভেন্ট থেকে সদস্যতা বাতিল করা উচিত)।

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

(*) প্রকৃতপক্ষে, সাবস্ক্রিপশনগুলি হ্যান্ডল করার একটি পরিষ্কার উপায় হ'ল বুলিয়ান ফেরত ফাংশনগুলির জন্য একটি মাল্টিকাস্ট ডেলিগেট টাইপ থাকবে; যদি এই জাতীয় প্রতিনিধি দ্বারা ডাকা কোনও ফাংশন সত্যটি প্রত্যাবর্তন করে তবে প্রতিনিধি সেই বস্তুটি সরিয়ে ফেলতে প্যাচ করা হবে। এর অর্থ হ'ল প্রতিনিধিরা আর প্রকৃতপক্ষে অপরিবর্তনীয় হবে না, তবে থ্রেড-নিরাপদ পদ্ধতিতে (যেমন উদ্যানের রেফারেন্সটি বাতিল করে এবং মাল্টিকাস্ট ডেলিগেট কোডটি কোনও এমবেডড নাল অবজেক্টের রেফারেন্সকে উপেক্ষা করে) এই পরিবর্তনটি কার্যকর করা উচিত should এই দৃশ্যের অধীনে, কোনও নিষ্পত্তিযোগ্য অবজেক্টের কাছে প্রকাশের এবং ইভেন্টের চেষ্টা খুব পরিষ্কারভাবে পরিচালনা করা যেতে পারে, ঘটনাটি কোথা থেকে এসেছে তা নির্বিশেষে।


2

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

ইভেন্ট হ্যান্ডলারের অভ্যন্তরে আমরা যে ডেটাটি পাস করতে চাই তা অন্য ডেটার জন্য আরেকটি ইভেন্টআর্গস র‌্যাপার বিকাশ করা দরকার, কেন কেন সরাসরি সেই ডেটা সেখানে পাস করা যায় না। কোডের নিম্নলিখিত বিভাগগুলি বিবেচনা করুন

[উদাহরণ 1]

public delegate void ConnectionEventHandler(Server sender, Connection connection);

public partial class Server
{
    protected virtual void OnClientConnected(Connection connection)
    {
        if (ClientConnected != null) ClientConnected(this, connection);
    }

    public event ConnectionEventHandler ClientConnected;
}

[উদাহরণ 2]

public delegate void ConnectionEventHandler(object sender, ConnectionEventArgs e);

public class ConnectionEventArgs : EventArgs
{
    public Connection Connection { get; private set; }

    public ConnectionEventArgs(Connection connection)
    {
        this.Connection = connection;
    }
}

public partial class Server
{
    protected virtual void OnClientConnected(Connection connection)
    {
        if (ClientConnected != null) ClientConnected(this, new ConnectionEventArgs(connection));
    }

    public event ConnectionEventHandler ClientConnected;
}

2
হ্যাঁ, সিস্টেম থেকে উত্তরাধিকারসূত্রে পৃথক শ্রেণি তৈরি করা vent আপনার যদি কখনও আপনার কোড পরিবর্তন করার প্রয়োজন হয় না, তবে আপনার পন্থা ভাল। তবে বাস্তবতাটি হ'ল আপনার ভবিষ্যতের সংস্করণে ইভেন্টটির কার্যকারিতা বাড়াতে এবং ইভেন্টের যুক্তিতে বৈশিষ্ট্য যুক্ত করার প্রয়োজন হতে পারে। আপনার দৃশ্যে আপনাকে ইভেন্টের হ্যান্ডলারের স্বাক্ষরে অতিরিক্ত ওভারলোড বা paraচ্ছিক পরামিতি যুক্ত করতে হবে। এটি ভিবিএ এবং লেগ্যাসি ভিবি .0.০ এ ব্যবহৃত একটি পদ্ধতির, যা কার্যক্ষম, তবে বাস্তবে কিছুটা কুৎসিত।
মাইক রোজেনব্লুম

1
ইভেন্টআর্গস থেকে উত্তরাধিকার সূত্রে, ভবিষ্যতের সংস্করণটি আপনার পুরানো ইভেন্ট আর্গুমেন্ট ক্লাস থেকে উত্তরাধিকার সূত্রে উত্তম হতে পারে। সমস্ত পুরানো কলাররা আপনার নতুন ইভেন্টের যুক্তি শ্রেণীর বেস ক্লাসের বিরুদ্ধে কাজ করে এখনও ঠিক ঠিক তেমন কাজ করতে পারে। খুব পরিষ্কার. আপনার জন্য আরও কাজ করা, তবে আপনার লাইব্রেরির উপর নির্ভরশীল কোনও কলকারীদের জন্য ক্লিনার er
মাইক রোজেনব্লুম

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

1

বর্তমান পরিস্থিতির সাথে (প্রেরকটি অবজেক্ট), আপনি সহজেই একাধিক ইভেন্টের সাথে একটি পদ্ধতি সংযুক্ত করতে পারেন:

button.Click += ClickHandler;
label.Click += ClickHandler;

void ClickHandler(object sender, EventArgs e) { ... }

যদি প্রেরক জেনেরিক হয়, ক্লিক-ইভেন্টের লক্ষ্যটি টাইপ বোতাম বা লেবেল নয়, তবে নিয়ন্ত্রণ টাইপ (কারণ ইভেন্টটি নিয়ন্ত্রণের উপর সংজ্ঞায়িত করা হয়) হতে পারে। সুতরাং বাটন-শ্রেণীর কিছু ইভেন্টের নিয়ন্ত্রণের ধরনের লক্ষ্য থাকবে, অন্যদের কাছে অন্যান্য লক্ষ্যর প্রকার থাকবে।


2
টমি, আমি প্রস্তাব করছি সিস্টেমের সাথে আপনি ঠিক একই জিনিসটি করতে পারেন । এই দৃ strong়-টাইপ করা ইভেন্টগুলি পরিচালনা করতে আপনি এখনও একটি স্ট্যান্ডার্ড ইভেন্ট হ্যান্ডলার ব্যবহার করতে পারেন যার একটি 'অবজেক্ট প্রেরক' প্যারামিটার রয়েছে। (কোডের উদাহরণটি দেখুন যে আমি এখন মূল পোস্টে যুক্ত করেছি))
মাইক রোজেনব্লুম

হ্যাঁ, আমি সম্মত, মানক সম্পর্কে ভাল জিনিস এটি। নেট ইভেন্টগুলি, গৃহীত!
Lu4

1

আপনি যা করতে চান তাতে কোনও সমস্যা আছে বলে আমি মনে করি না। বেশিরভাগ ক্ষেত্রে, আমি সন্দেহ করি যে object senderপূর্বের ২.০ কোডটি সমর্থন অব্যাহত রাখতে প্যারামিটারটি রয়ে গেছে।

আপনি যদি সত্যই কোনও সর্বজনীন API এর জন্য এই পরিবর্তনটি করতে চান তবে আপনি নিজের বেস এমনকি ইভেন্টআর্গ ক্লাস তৈরির বিষয়টি বিবেচনা করতে পারেন। এটার মতো কিছু:

public class DataEventArgs<TSender, TData> : EventArgs
{
    private readonly TSender sender, TData data;

    public DataEventArgs(TSender sender, TData data)
    {
        this.sender = sender;
        this.data = data;
    }

    public TSender Sender { get { return sender; } }
    public TData Data { get { return data; } }
}

তারপরে আপনি আপনার ইভেন্টগুলি এভাবে ঘোষণা করতে পারেন

public event EventHandler<DataEventArgs<MyClass, int>> SomeIndexSelected;

এবং এর মতো পদ্ধতিগুলি:

private void HandleSomething(object sender, EventArgs e)

এখনও সাবস্ক্রাইব করতে সক্ষম হবে।

সম্পাদনা

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

এর সাথে DataEventArgsস্টিক করার একটি সুবিধা হ'ল ইভেন্ট ইভেন্ট চেইন করতে পারেন, প্রেরককে পরিবর্তন করতে (শেষ প্রেরকের প্রতিনিধিত্ব করতে) ইভেন্ট ইভেন্টগুলি যখন মূল প্রেরককে ধরে রাখে।


আরে মাইকেল, এটি একটি সুন্দর ঝরঝরে বিকল্প। আমি এটা পছন্দ করি. আপনি যেমন উল্লেখ করেছেন, তবে 'প্রেরক' পরামিতি কার্যকরভাবে দু'বার পাস করা বাড়াবাড়ি। এখানে একটি অনুরূপ পদ্ধতির আলোচনা করা হয়েছে: স্ট্যাকওভারফ্লো.com / প্রশ্নস / ৮০৯60০৯/২ , এবং sensক্যমত্য বলে মনে হয় যে এটি খুব মানসম্মত নয়। এই কারণেই আমি এখানে দৃ strong়-টাইপযুক্ত 'প্রেরক' ধারণাটি বলতে দ্বিধা বোধ করি। (যদিও আপনাকে ভালভাবে গ্রহণ করা হয়েছে বলে মনে হচ্ছে, তাই আমি সন্তুষ্ট))
মাইক রোজেনব্লাম

1

এটার জন্য যাও. অ উপাদান উপাদান ভিত্তিক কোডের জন্য, আমি প্রায়শই ইভেন্ট স্বাক্ষরগুলি সরল করে তুলি

public event Action<MyEventType> EventName

কোথা MyEventTypeথেকে উত্তরাধিকারী হয় না EventArgs। কেন বিরক্ত হবে, যদি আমি ইভেন্টআরগসের কোনও সদস্যকে ব্যবহার করার ইচ্ছা না করি।


1
একমত! আমাদের নিজেদের বানর বোধ করা উচিত কেন?
Lu4

1
+ 1-এড, এটি আমিও ব্যবহার করি। মাঝে মাঝে সরলতা জেতা! অথবা এমনকি event Action<S, T>, event Action<R, S, T>ইত্যাদি আমার কাছে Raiseতাদের কাছে থ্রেড-সুরক্ষিতভাবে একটি এক্সটেনশন পদ্ধতি রয়েছে :)
নওফাল 15'13
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.