সুস্পষ্ট টাইপকাস্টের সাহায্যে উদ্ভূত শ্রেণীর রেফারেন্সে কোনও বেস ক্লাস অবজেক্টটি অর্পণ করা সম্ভব?


89

C # তে স্পষ্টত টাইপকাস্টের সাহায্যে উত্পন্ন শ্রেণি রেফারেন্সের জন্য বেস শ্রেণীর অবজেক্টকে বরাদ্দ করা সম্ভব ?.

আমি এটি চেষ্টা করেছি এবং এটি একটি রান-টাইম ত্রুটি তৈরি করে।

উত্তর:


100

না। উত্পন্ন শ্রেণীর জন্য একটি রেফারেন্সটি অবশ্যই উত্পন্ন শ্রেণীর উদাহরণ (বা নাল) উল্লেখ করতে হবে। অন্যথায় আপনি এটি আচরণ করবে বলে কীভাবে আশা করবেন?

উদাহরণ স্বরূপ:

object o = new object();
string s = (string) o;
int i = s.Length; // What can this sensibly do?

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


72
@ মাইক: কোডটি ঠিকঠাকভাবে সংকলন করে। এটি কার্যকর হওয়ার সময়েই পড়ে যায় :)
জন স্কিটি

4
তারপরে ঠিক কী ঘটে যখন আমরা বেস লিখি = নতুন ডেরাইভড (); ? এটি উভয় বেস এবং উদ্ভূত শ্রেণীর জন্য অবজেক্ট তৈরি করবে?
আশিফ নাটালিয়া

4
@ আকি: না, এটি টাইপের একটি একক অবজেক্ট তৈরি করে Derivedতবে আপনি একটি Derivedরেফারেন্সকে রেফারেন্স হিসাবে বিবেচনা করতে পারেন Base
জন স্কিটি

সুতরাং এই দুটি বিবৃতি জন্য ফলাফল বস্তুর মধ্যে কোন পার্থক্য আছে? বেস খ = নতুন বেস () এবং বেস খ = নতুন উত্পন্ন ()? একে অপরকে ব্যবহার করে কী লাভ?
আশিফ নাটালিয়া

4
@ আকি: হ্যাঁ, একটির উদাহরণ তৈরি করে Baseএবং অন্যটি একটি উদাহরণ তৈরি করে Derived। যদি আপনি কোনও ভার্চুয়াল পদ্ধতিতে কল করেন bযার উপরে ওভাররাইড করা হয়েছে Derived, আপনি Derivedযদি উদাহরণটি পেয়ে থাকেন তবে আপনি আচরণটি দেখতে পাবেন Derived। তবে স্ট্যাক ওভারফ্লো মন্তব্য থ্রেডের বিবরণে যাওয়া সত্যিই উপযুক্ত নয় - এটি সত্যিই একটি ভাল সি # বই বা টিউটোরিয়াল পড়া উচিত, কারণ এটি বেশ মৌলিক উপাদান stuff
জন স্কিটি

47

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

আপনি একটি বর্গ শ্রেণীর অবজেক্টটিকে প্যারামিটার হিসাবে গ্রহণ করে, মানগুলি অনুলিপি করে উত্পন্ন ক্লাসে একটি নির্মাণকারী লিখতে পারেন।

এটার মতো কিছু:

public class Base {
    public int Data;

    public void DoStuff() {
        // Do stuff with data
    }
}

public class Derived : Base {
    public int OtherData;

    public Derived(Base b) {
        this.Data = b.Data;
        OtherData = 0; // default value
    }

    public void DoOtherStuff() {
        // Do some other stuff
    }
}

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

Base b = new Base();//base class
Derived d = new Derived();//derived class

b.DoStuff();    // OK
d.DoStuff();    // Also OK
b.DoOtherStuff();    // Won't work!
d.DoOtherStuff();    // OK

d = new Derived(b);  // Copy construct a Derived with values of b
d.DoOtherStuff();    // Now works!

23

আমার এই সমস্যাটি ছিল এবং একটি পদ্ধতি যুক্ত করে এটি সমাধান করেছি যা একটি টাইপ প্যারামিটার নেয় এবং বর্তমান বস্তুকে সেই ধরণের রূপান্তর করে।

public TA As<TA>() where TA : Base
{
    var type = typeof (TA);
    var instance = Activator.CreateInstance(type);

     PropertyInfo[] properties = type.GetProperties();
     foreach (var property in properties)
     {
         property.SetValue(instance, property.GetValue(this, null), null);
     }

     return (TA)instance;
}

এর অর্থ আপনি নিজের কোডটিতে এটি ব্যবহার করতে পারেন:

var base = new Base();
base.Data = 1;
var derived = base.As<Derived>();
Console.Write(derived.Data); // Would output 1

আপনার প্রাপ্ত বর্গের (বেস শ্রেণি) প্রকারটি পেতে এবং বৈশিষ্ট্য নির্ধারণের জন্য ব্যবহার করা উচিত কারণ এগুলি সেই মানগুলি যা আপনি প্রাপ্ত শ্রেণীর উপর মানচিত্র করতে চান।
বোওফোলা

4
যদি আপনার এমন বৈশিষ্ট্য থাকে যা উত্পন্ন টাইপে লেখা যায় না তবে আপনার সম্ভবত এটিতে পরিবর্তন করা উচিত: যদি (সম্পত্তি.CanWrite) সম্পত্তি.SetValue (উদাহরণস্বরূপ, সম্পত্তি.GetValue (এটি, নাল), নাল);
ব্যবহারকারী 3478586

10

অন্য অনেকে উত্তর দিয়েছেন, না।

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

বেস ক্লাসে এই কোড:

    public T As<T>()
    {
        var type = typeof(T);
        var instance = Activator.CreateInstance(type);

        if (type.BaseType != null)
        {
            var properties = type.BaseType.GetProperties();
            foreach (var property in properties)
                if (property.CanWrite)
                    property.SetValue(instance, property.GetValue(this, null), null);
        }

        return (T) instance;
    }

অনুমতি:

    derivedObject = baseObect.As<derivedType>()

যেহেতু এটি প্রতিবিম্ব ব্যবহার করে তাই এটি "ব্যয়বহুল"। সেই অনুযায়ী ব্যবহার করুন।


আমি কেবল এটি চেষ্টা করে দেখেছি এবং বুঝতে পেরেছি, সুস্পষ্ট অপারেটর (এবং এটিও অন্তর্ভুক্ত অপারেটর) ওভারলোড করে আরও উন্নত করা যেতে পারে .. তবে - সংকলক এটি অনুমতি দেবে না: user-defined conversions to or from a base class are not allowed আমি এর কারণগুলি দেখছি, তবে হতাশ, এটি যদি এত মজা পেত যে এটি যদি এটির অনুমতি দেয় তবে ..
হেনরিক

@ এমইসি: আমি লক্ষ্য করেছি যে আপনি যেখানে dropped টি: মাইবেসক্লাস` অংশটি ফেলে দিয়েছিলেন এবং if (type.BaseType != null)মার্কাস কানপেন জোহানসনের এ-এর সাথে সম্পর্কিত বিবৃতি যুক্ত করেছেন তা কেন? তার মানে এটি কলগুলিতে মাইবেসক্লাস (বা এই বিষয়টির জন্য কিছু) থেকে প্রাপ্ত নয় এমন কোনও প্রকারের অনুমতি দেবে। আমি বুঝতে পেরেছি যে এটি মাইডেরাইভডজেক্টে অ্যাসাইন করা থাকলে এটি এখনও একটি সংকলক ত্রুটি সৃষ্টি করবে, তবে এটি যদি কেবল এক্সপ্রেশন হিসাবে ব্যবহৃত হয় তবে এটি সংকলিত হবে এবং রান-টাইমে কেবল "মাইবেসঅবজেক্ট" থেকে অনুলিপি করা কোনও ডেটা ছাড়াই একটি মাইডেরিভডজেক্ট তৈরি করবে। আমি এটির জন্য কোনও ব্যবহারের বিষয়টি কল্পনা করতে পারি না।
টম

@ টম, দেরীতে জবাব, কিন্তু ভেবেছিল এটি এখনও কার্যকর হতে পারে। আপনার প্রশ্নের সর্বোত্তম প্রতিক্রিয়া সম্ভবত এটিই বলা হবে যে "As" নামটি আরও ভাল "AsOrDefault" হত। মূলত আমরা এই ফলাফলটি নিতে পারি এবং এটি একটি ডিফল্টের সাথে তুলনা করতে পারি যেমন লিনকের সিঙ্গেলঅরডিফল্ট বা ফার্স্টআরডিফল্ট ব্যবহার করার সময় আমরা করি।
এমইসি

7

না এটি সম্ভব নয়, সুতরাং আপনার রানটাইম ত্রুটি।

তবে আপনি বেস ক্লাসের ধরণের ভেরিয়েবলের জন্য একটি উত্পন্ন ক্লাসের উদাহরণ অর্পণ করতে পারেন।


7

জসনকনভার্টের সাথে সমাধান (টাইপকাস্টের পরিবর্তে)

আজ আমি একই সমস্যার মুখোমুখি হয়েছি এবং ব্যবহার করে সমস্যার একটি সহজ এবং দ্রুত সমাধান পেয়েছি JsonConvert

var base = new BaseClass();
var json = JsonConvert.SerializeObject(base);
DerivedClass derived = JsonConvert.DeserializeObject<DerivedClass>(json);

আমি এক্সটেনশন পদ্ধতিতে নীচে এটি আবার উত্তর দিয়েছি। হ্যাঁ, এই উত্তর।
প্যাট্রিক নট

5

এখানে সবাই যেমন বলেছে, এটি সরাসরি সম্ভব নয়।

আমি যে পদ্ধতিটি পছন্দ করি এবং এটি পরিষ্কার, তা হ'ল অটোম্যাপারের মতো একটি অবজেক্ট ম্যাপার ব্যবহার করা

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


3

@ Ybo এর উত্তরে সম্প্রসারণ করা - এটি সম্ভব নয় কারণ আপনার বেস ক্লাসের উদাহরণটি উত্পন্ন শ্রেণীর উদাহরণ নয়। এটি কেবল বেস শ্রেণির সদস্যদের সম্পর্কেই জানে এবং উত্পন্ন শ্রেণীর সদস্যদের সম্পর্কে কিছুই জানে না।

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


3

আপনি একটি ভেরিয়েবল কাস্ট করতে পারেন যা উত্পন্ন শ্রেণীর ধরণের কাছে বেস-শ্রেণি হিসাবে টাইপ করা হয়; তবে প্রয়োজনীয়তার সাথে এটি একটি রানটাইম চেক করবে, জড়িত প্রকৃত বস্তুটি সঠিক ধরণের কিনা তা দেখতে।

একবার তৈরি হয়ে গেলে, কোনও সামগ্রীর ধরণ পরিবর্তন করা যায় না (কমপক্ষে নয়, এটি একই আকারের নাও হতে পারে)। তবে আপনি দ্বিতীয় রূপের একটি নতুন উদাহরণ তৈরি করে একটি উদাহরণ রূপান্তর করতে পারেন - তবে আপনাকে রূপান্তর কোডটি ম্যানুয়ালি লিখতে হবে।


2

না, এটা সম্ভব নয়।

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


2
class Program
{
    static void Main(string[] args)
    {
        a a1 = new b();  
        a1.print();  
    }
}
class a
{
    public a()
    {
        Console.WriteLine("base class object initiated");
    }
    public void print()
    {
        Console.WriteLine("base");
    }
}
class b:a
{
    public b()
    {
        Console.WriteLine("child class object");
    }
    public void print1()
    {
        Console.WriteLine("derived");
    }
}

}

যখন আমরা একটি শিশু শ্রেণি অবজেক্ট তৈরি করি তখন বেস শ্রেণীর অবজেক্টটি স্বয়ংক্রিয়ভাবে চালিত হয় সুতরাং বেস শ্রেণীর রেফারেন্স ভেরিয়েবলটি শিশু শ্রেণীর অবজেক্টকে নির্দেশ করতে পারে।

তবে তদ্বিপরীত নয় কারণ একটি শিশু শ্রেণির রেফারেন্স ভেরিয়েবল বেস ক্লাস অবজেক্টে নির্দেশ করতে পারে না কারণ কোনও শিশু শ্রেণীর অবজেক্ট তৈরি করা হয়নি is

এবং আরও লক্ষ্য করুন যে বেস শ্রেণীর রেফারেন্স ভেরিয়েবল কেবল বেস শ্রেণীর সদস্যকে কল করতে পারে।


2

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

আমি এখানে এটি কিভাবে। একটি ছোট কোড নমুনা আমার ব্যাখ্যা অনুসরণ করবে।

  1. বেস ক্লাস থেকে আপনার অবজেক্টের একটি উদাহরণ তৈরি করুন এবং সেই অনুযায়ী সেট করুন।

  2. নিউটনসফট জসনের "জসন কনভার্ট" ক্লাস ব্যবহার করে সেই বস্তুকে জসন স্ট্রিংয়ে সিরিয়াল করুন।

  3. এখন পদক্ষেপ 2 তে তৈরি জসন স্ট্রিংটি ডিসরিয়ালাইজ করে আপনার সাব ক্লাসের অবজেক্ট তৈরি করুন এটি বেস ক্লাসের সমস্ত বৈশিষ্ট্য সহ আপনার সাব ক্লাসের একটি উদাহরণ তৈরি করবে।

এটি একটি মোহন মত কাজ করে! তো .. কখন এটি দরকারী? কিছু লোক জিজ্ঞাসা করেছিল যে এটি কখন বোঝা যাবে এবং ওপি'র স্কিমাকে পরিবর্তনের পরামর্শ দিয়েছিল যাতে আপনি এটিকে স্থানীয়ভাবে বর্গ উত্তরাধিকারের সাথে করতে পারবেন না (নেট।)।

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

চূড়ান্ত আউটপুট হ'ল সমস্ত বিকল্পের সেট সহ একটি উত্পন্ন শ্রেণি। অতিরিক্ত নতুন সাব ক্লাসের জন্য এটি পুনরাবৃত্তি করতে কোডের কয়েকটি লাইন লাগবে। এটি সহজ, এবং এটি যাদু কাজ করতে খুব চেষ্টা করা এবং পরীক্ষিত প্যাকেজ (নিউটনসফট) ব্যবহার করে।

এই উদাহরণ কোডটি vb.Net, তবে আপনি সহজেই সি # তে রূপান্তর করতে পারেন।

' First, create the base settings object.
    Dim basePMSettngs As gtmaPayMethodSettings = gtmaPayments.getBasePayMethodSetting(payTypeId, account_id)
    Dim basePMSettingsJson As String = JsonConvert.SerializeObject(basePMSettngs, Formatting.Indented)

    ' Create a pmSettings object of this specific type of payment and inherit from the base class object
    Dim pmSettings As gtmaPayMethodAimACHSettings = JsonConvert.DeserializeObject(Of gtmaPayMethodAimACHSettings)(basePMSettingsJson)

ব্যবহার C # এবং Newtonsoft.Json: var destObject = JsonConvert.DeserializeObject<DestinationType>(JsonConvert.SerializeObject(srcObject));। আমি এটি কেবল ইউনিট টেস্ট এবং অন্যান্য অ-উত্পাদন "হ্যাকিং" এর জন্য ব্যবহার করব!
ভাবুনফাফা নাম্বার

2

আপনি একটি এক্সটেনশন ব্যবহার করতে পারেন:

public static void CopyOnlyEqualProperties<T>(this T objDest, object objSource) where T : class
    {
        foreach (PropertyInfo propInfo in typeof(T).GetProperties())
            if (objSource.GetType().GetProperties().Any(z => z.Name == propInfo.Name && z.GetType() == propInfo.GetType()))
                propInfo.SetValue(objDest, objSource.GetType().GetProperties().First(z => z.Name == propInfo.Name && z.GetType() == propInfo.GetType()).GetValue(objSource));
    }

কোডে:

public class BaseClass
{
  public string test{ get; set;}
}
public Derived : BaseClass
{
//Some properies
}

public void CopyProps()
{
   BaseClass baseCl =new BaseClass();
   baseCl.test="Hello";
   Derived drv=new Derived();
   drv.CopyOnlyEqualProperties(baseCl);
   //Should return Hello to the console now in derived class.
   Console.WriteLine(drv.test);

}

1

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

public static T Cast<T>(object obj)
{
    return (T)obj;
}

...

//Invoke parent object's json function
MethodInfo castMethod = this.GetType().GetMethod("Cast").MakeGenericMethod(baseObj.GetType());
object castedObject = castMethod.Invoke(null, new object[] { baseObj });
MethodInfo jsonMethod = baseObj.GetType ().GetMethod ("ToJSON");
return (string)jsonMethod.Invoke (castedObject,null);

1

আপনি জেনেরিক ব্যবহার করে এটি করতে পারেন।

public class BaseClass
{
    public int A { get; set; }
    public int B { get; set; }
    private T ConvertTo<T>() where T : BaseClass, new()
    {
         return new T
         {
             A = A,
             B = B
         }
    }

    public DerivedClass1 ConvertToDerivedClass1()
    {
         return ConvertTo<DerivedClass1>();
    }

    public DerivedClass2 ConvertToDerivedClass2()
    {
         return ConvertTo<DerivedClass2>();
    }
}

public class DerivedClass1 : BaseClass
{
    public int C { get; set; }
}

public class DerivedClass2 : BaseClass
{
    public int D { get; set; }
}

আপনি এই পদ্ধতির ব্যবহার করে তিনটি সুবিধা পাবেন।

  1. আপনি কোডটি নকল করছেন না
  2. আপনি প্রতিবিম্ব ব্যবহার করছেন না (যা ধীর)
  3. আপনার সমস্ত রূপান্তর এক জায়গায়

1

আমি জানি এটি পুরানো তবে আমি এটি বেশ কিছু সময়ের জন্য সফলভাবে ব্যবহার করেছি।

   private void PopulateDerivedFromBase<TB,TD>(TB baseclass,TD derivedclass)
    {
        //get our baseclass properties
        var bprops = baseclass.GetType().GetProperties();
        foreach (var bprop in bprops)
        {
            //get the corresponding property in the derived class
            var dprop = derivedclass.GetType().GetProperty(bprop.Name);
            //if the derived property exists and it's writable, set the value
            if (dprop != null && dprop.CanWrite)
                dprop.SetValue(derivedclass,bprop.GetValue(baseclass, null),null);
        }
    } 

1

আমি পূর্ববর্তী উত্তরের কয়েকটি অংশ (সেই লেখকদের ধন্যবাদ) একত্রিত করেছিলাম এবং আমরা ব্যবহার করছি এমন দুটি পদ্ধতির সাথে একটি সাধারণ স্ট্যাটিক ক্লাস একসাথে রেখেছি।

হ্যাঁ, এটি সহজ, না এটি সমস্ত পরিস্থিতিতে আচ্ছাদন করে না, হ্যাঁ এটি প্রসারিত এবং আরও ভাল করা যেতে পারে, না এটি নিখুঁত নয়, হ্যাঁ এটি সম্ভবত আরও দক্ষ করা যেতে পারে, না কাটা রুটি থেকে এটি সবচেয়ে বড় জিনিস নয়, হ্যাঁ আছে ভারি ব্যবহার, ইত্যাদি ইত্যাদির জন্য পুরোপুরি দৃust় নুগেট প্যাকেজ অবজেক্ট ম্যাপারগুলি এখানে রয়েছে - তবে এটি আমাদের প্রাথমিক প্রয়োজনে কাজ করে :)

এবং অবশ্যই এটি কোনও অবজেক্ট থেকে যে কোনও অবজেক্টে, প্রাপ্ত বা না হওয়াতে মানচিত্র তৈরি করার চেষ্টা করবে (কেবলমাত্র সর্বজনীন বৈশিষ্ট্য যা অবশ্যই একই নামযুক্ত রয়েছে - বাকিগুলিকে উপেক্ষা করে)।

ব্যবহার:

SesameStreetCharacter puppet = new SesameStreetCharacter() { Name = "Elmo", Age = 5 };

// creates new object of type "RealPerson" and assigns any matching property 
// values from the puppet object 
// (this method requires that "RealPerson" have a parameterless constructor )
RealPerson person = ObjectMapper.MapToNewObject<RealPerson>(puppet);

// OR

// create the person object on our own 
// (so RealPerson can have any constructor type that it wants)
SesameStreetCharacter puppet = new SesameStreetCharacter() { Name = "Elmo", Age = 5 };
RealPerson person = new RealPerson("tall") {Name = "Steve"};

// maps and overwrites any matching property values from 
// the puppet object to the person object so now our person's age will get set to 5 and
// the name "Steve" will get overwritten with "Elmo" in this example
ObjectMapper.MapToExistingObject(puppet, person);

স্ট্যাটিক ইউটিলিটি ক্লাস:

public static class ObjectMapper
{
    // the target object is created on the fly and the target type 
    // must have a parameterless constructor (either compiler-generated or explicit) 
    public static Ttarget MapToNewObject<Ttarget>(object sourceobject) where Ttarget : new()
    {
        // create an instance of the target class
        Ttarget targetobject = (Ttarget)Activator.CreateInstance(typeof(Ttarget));

        // map the source properties to the target object
        MapToExistingObject(sourceobject, targetobject);

        return targetobject;
    }

    // the target object is created beforehand and passed in
    public static void MapToExistingObject(object sourceobject, object targetobject)
    {
        // get the list of properties available in source class
        var sourceproperties = sourceobject.GetType().GetProperties().ToList();

        // loop through source object properties
        sourceproperties.ForEach(sourceproperty => {

            var targetProp = targetobject.GetType().GetProperty(sourceproperty.Name);

            // check whether that property is present in target class and is writeable
            if (targetProp != null && targetProp.CanWrite)
            {
                // if present get the value and map it
                var value = sourceobject.GetType().GetProperty(sourceproperty.Name).GetValue(sourceobject, null);
                targetobject.GetType().GetProperty(sourceproperty.Name).SetValue(targetobject, value, null);
            }
        });
    }
}

1

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

class Person
{
    // Copy constructor 
    public Person(Person previousPerson)
    {
        Name = previousPerson.Name;
        Age = previousPerson.Age;
    }

    // Copy constructor calls the instance constructor.
    public Person(Person previousPerson)
        : this(previousPerson.Name, previousPerson.Age)
    {
    }

    // Instance constructor.
    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }

    public int Age { get; set; }

    public string Name { get; set; }
}

অতীতে এই সমস্যাটি থাকার কারণে কনস্ট্রাক্টরের অধীনে মাইক্রোসফ্ট সি # ডকুমেন্টেশন উল্লেখ করেছেন।


0

আরেকটি সমাধান হ'ল এটির মতো এক্সটেনশন পদ্ধতি যুক্ত করা:

 public static void CopyProperties(this object destinationObject, object sourceObject, bool overwriteAll = true)
        {
            try
            {
                if (sourceObject != null)
                {
                    PropertyInfo[] sourceProps = sourceObject.GetType().GetProperties();
                    List<string> sourcePropNames = sourceProps.Select(p => p.Name).ToList();
                    foreach (PropertyInfo pi in destinationObject.GetType().GetProperties())
                    {
                        if (sourcePropNames.Contains(pi.Name))
                        {
                            PropertyInfo sourceProp = sourceProps.First(srcProp => srcProp.Name == pi.Name);
                            if (sourceProp.PropertyType == pi.PropertyType)
                                if (overwriteAll || pi.GetValue(destinationObject, null) == null)
                                {
                                    pi.SetValue(destinationObject, sourceProp.GetValue(sourceObject, null), null);
                                }
                        }
                    }
                }
            }
            catch (ApplicationException ex)
            {
                throw;
            }
        }

তারপরে প্রতিটি উত্পন্ন ক্লাসে এমন একজন কনস্ট্রাক্টর রয়েছে যা বেস ক্লাস গ্রহণ করে:

  public class DerivedClass: BaseClass
    { 
        public DerivedClass(BaseClass baseModel)
        {
            this.CopyProperties(baseModel);
        }
    }

এটি ইতিমধ্যে সেট (নাল নয়) সেট করা থাকলে বা গন্তব্য বৈশিষ্ট্যগুলি ওভাররাইট করে।


0

C # তে স্পষ্টত টাইপকাস্টের সাহায্যে উত্পন্ন শ্রেণি রেফারেন্সের জন্য বেস শ্রেণীর অবজেক্টকে বরাদ্দ করা সম্ভব ?.

কেবল সুস্পষ্ট নয়, অন্তর্নিহিত রূপান্তরগুলিও সম্ভব।

সি # ভাষা এ জাতীয় রূপান্তর অপারেটরদের অনুমতি দেয় না, তবে আপনি খাঁটি সি # ব্যবহার করে তাদের লিখতে পারেন এবং তারা কাজ করে। নোট করুন যে শ্রেণীটি যা অন্তর্নিহিত রূপান্তর অপারেটর ( Derived) এবং অপারেটর ( ) ব্যবহার করে এমন শ্রেণি Programপৃথক সমাবেশে সংজ্ঞায়িত করতে হবে (যেমন Derivedশ্রেণিটি এমন একটিতে রয়েছে যা বর্গটি ধারণ করে library.dllরেফারেন্স করা হয় )।program.exeProgram

//In library.dll:
public class Base { }

public class Derived {
    [System.Runtime.CompilerServices.SpecialName]
    public static Derived op_Implicit(Base a) {
        return new Derived(a); //Write some Base -> Derived conversion code here
    }

    [System.Runtime.CompilerServices.SpecialName]
    public static Derived op_Explicit(Base a) {
        return new Derived(a); //Write some Base -> Derived conversion code here
    }
}

//In program.exe:
class Program {
    static void Main(string[] args) {
        Derived z = new Base(); //Visual Studio can show squiggles here, but it compiles just fine.
    }
}

আপনি যখন ভিজ্যুয়াল স্টুডিওতে প্রজেক্ট রেফারেন্স ব্যবহার করে গ্রন্থাগারটি উল্লেখ করেন, আপনি যখন অন্তর্নিহিত রূপান্তরটি ব্যবহার করেন তখন ভিএস স্কাগলগুলি দেখায়, তবে এটি ঠিক সূক্ষ্ম সংকলন করে। আপনি যদি কেবলমাত্র উল্লেখ করে থাকেন library.dllতবে কোনও স্কুইগল নেই।


এটা কি কালো যাদু?!? এছাড়াও, "ডেরিভড জেড = নতুন বেস () কীভাবে আমাকে" বেসক্লাস বেসওবিজে; ডেরিভডক্লস ডেরাইভডঅবিজ; ডেরিভডব্লস = (ডেরিভডসিএলস) বেসওবজ "(ওপি'র কিউ) করতে সহায়তা করে? এছাড়াও, System.Runtime.CompilerServices.SpecialNameঅ্যাট্রিবিউট কী করে ? প্রাচীনতম উপলব্ধ (2.0) থেকে "বর্তমান সংস্করণ" (4.6? "কেউ? কেউ?") থেকে প্রতিটি সংস্করণের জন্য ডকগুলি এটি যা বলে তা বলে না, তবে বলে যে "স্পেশালনামঅ্যাট্রিবিউট শ্রেণি বর্তমানে। নেট এ ব্যবহৃত হয় না ফ্রেমওয়ার্ক, তবে ভবিষ্যতে ব্যবহারের জন্য সংরক্ষিত। দেখুন: [লিঙ্ক] ( এমএসডিএন.মাইক্রোসফটকম /en-us/library/ms146064(v=vs.100).aspx )।
টম

> "এটি কোন কালো যাদু?!?" এটিকে বলা হয় নেট ফ্রেমওয়ার্ক (সিএলআর, আইএল, বিসিএল)। আইএল, সি # এবং ভিবি ভাষার বৈশিষ্ট্য সেট এক নয়। ভিবিতে এমন বৈশিষ্ট্য রয়েছে যা সি # সমর্থন করে না। আইএলে এমন বৈশিষ্ট্য রয়েছে যা সি # সমর্থন করে না। সি # তে বিধিনিষেধগুলি রয়েছে যা বরং স্বেচ্ছাচারী এবং অন্তর্নিহিত আইএল (যেমন where T : Delegateবা প্যারামিট্রাইজড বৈশিষ্ট্যগুলি ওরফে সূচক ইত্যাদি ইত্যাদি) তে বিদ্যমান নয়।
অর্ক-কুন

> "এছাড়াও," ডেসিভড জেড = নতুন বেস () "কীভাবে আমাকে" বেসসিএল বেসবজ "করতে সহায়তা করে; ডেরিভডক্লাস ডেরাইভড ওবিজে; deridedObj = (ডেরিভডক্লসস) বেসওবজ "(ওপি'র প্রশ্ন)?" এটা ঠিক আছে। এটি ওপির প্রশ্নের সমাধান করে। এবং আপনার এমনকি সুস্পষ্ট কাস্টের প্রয়োজন নেই।
অর্ক-কুন

> what does System.Runtime.CompilerServices.SpecialName Attribute do?যদি না আইএল পদ্ধতি চিহ্নিত করা হয় সঙ্গে সম্পত্তি accessors, ঘটনা accessors, কনস্ট্রাকটর, অপারেটর, indexers, ইত্যাদি: - এটি উচ্চ পর্যায়ের নেট ভাষার কিছু বিশেষ সুবিধা নির্মান দ্বারা উত্পাদিত পদ্ধতি চিহ্নিত করতে ব্যবহৃত হচ্ছে specialnameএটি দেখা যায় না হবে সম্পত্তি / ইভেন্ট / নির্মাতা হিসাবে এবং এটি কেবল একটি সাধারণ পদ্ধতি হিসাবে স্বীকৃত হবে। এই বৈশিষ্ট্যের সাথে যথাযথ-নামক পদ্ধতিগুলি ম্যানুয়ালি চিহ্নিত করা হ'ল ম্যানুয়ালি সংকলকের কাজটি কিছুটা করছে।
অর্ক-কুন

ভিবি.নেটের পাওয়ার অপারেটর রয়েছে। সি # করে না। আপনি কীভাবে ভিবি.নেট ব্যবহারের জন্য সি # তে পাওয়ার অপারেটরটি ওভারলোড করবেন? কেবল একটি op_Exponentপদ্ধতি সংজ্ঞায়িত করুন এবং specialnameএট্রিবিউট দিয়ে চিহ্নিত করুন ।
অর্ক-কুন


0

উত্সযুক্ত আইটেমটিতে সমস্ত বেস বৈশিষ্ট্য যুক্ত করার সর্বোত্তম উপায় হ'ল পোশাকের প্রতিচ্ছবি ব্যবহার করা। পদ্ধতি বা দৃষ্টান্ত তৈরি না করে এই কোডটি ব্যবহার করে দেখুন।

    public Derived(Base item) :base()
    {

        Type type = item.GetType();

        System.Reflection.PropertyInfo[] properties = type.GetProperties();
        foreach (var property in properties)
        {
            try
            {
                property.SetValue(this, property.GetValue(item, null), null);
            }
            catch (Exception) { }
        }

    }

0

আমি অসমত যে এটি সম্ভব নয়। আপনি এটি এর মতো করতে পারেন:

public class Auto 
{ 
    public string Make {get; set;}
    public string Model {get; set;}
}

public class Sedan : Auto
{ 
    public int NumberOfDoors {get; set;}
}

public static T ConvertAuto<T>(Sedan sedan) where T : class
{
    object auto = sedan;
    return (T)loc;
}

ব্যবহার:

var sedan = new Sedan();
sedan.NumberOfDoors = 4;
var auto = ConvertAuto<Auto>(sedan);

var auto =এখনও টাইপ করা হয়sedan
bendecko

0

এইভাবে আমি ক্ষেত্রগুলির জন্য এটি সমাধান করেছি। আপনি চাইলে বৈশিষ্ট্যগুলির মাধ্যমে একই পুনরাবৃত্তি করতে পারেন। আপনি nullইত্যাদির জন্য কিছু চেক করতে চাইতে পারেন তবে এটি ধারণা।

 public static DerivedClass ConvertFromBaseToDerived<BaseClass, DerivedClass>(BaseClass baseClass)
            where BaseClass : class, new()
            where DerivedClass : class, BaseClass, new()
        {
            DerivedClass derived = (DerivedClass)Activator.CreateInstance(typeof(DerivedClass));
            derived.GetType().GetFields().ToList().ForEach(field =>
            {
                var base_ = baseClass.GetType().GetField(field.Name).GetValue(baseClass);
                field.SetValue(derived, base_);

            });

            return derived;
        }

0

আপনি কেবল JSON এ বেস অবজেক্টটি সিরিয়ালাইজ করতে পারেন এবং তারপরে এটিকে উত্পন্ন বস্তুতে ডিসরিয়ালাইজ করতে পারেন।


0

Theতিহ্যবাহী সংবেদনে নয় ... জসনে রূপান্তর করুন, তারপরে আপনার অবজেক্টে, এবং বুম করুন! জেসির উপরের উত্তরটি আগে পোস্ট করা হয়েছিল, তবে এই প্রসারণ পদ্ধতিগুলি ব্যবহার করেনি যা প্রক্রিয়াটি এত সহজ করে তোলে। কয়েকটি এক্সটেনশন পদ্ধতি তৈরি করুন:

    public static string ConvertToJson<T>(this T obj)
    {
        return JsonConvert.SerializeObject(obj);
    }
    public static T ConvertToObject<T>(this string json)
    {
        if (string.IsNullOrEmpty(json))
        {
            return Activator.CreateInstance<T>();
        }
        return JsonConvert.DeserializeObject<T>(json);
    }

এগুলি আপনার সরঞ্জামবক্সে চিরকাল রাখুন, তারপরে আপনি সর্বদা এটি করতে পারেন:

var derivedClass = baseClass.ConvertToJson().ConvertToObject<derivedClass>();

আহ, জেএসওনের শক্তি।

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


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

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

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

-1

না, আমি জিজ্ঞাসা করা এই প্রশ্নটি দেখুন - জেনেরিক ব্যবহার করে .NET উপকাস্টিং ইন

সর্বোত্তম উপায় হ'ল ক্লাসে একটি ডিফল্ট কনস্ট্রাক্টর তৈরি করা, নির্মাণ করা এবং তারপরে একটি Initialiseপদ্ধতি কল করা

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