প্রতিবিম্ব ব্যবহার করে সি # তে ডিফল্ট কনস্ট্রাক্টর ছাড়াই টাইপের উদাহরণ তৈরি করা


98

নিম্নলিখিত শ্রেণিকে উদাহরণ হিসাবে ধরুন:

class Sometype
{
    int someValue;

    public Sometype(int someValue)
    {
        this.someValue = someValue;
    }
}

আমি তখন প্রতিবিম্বটি ব্যবহার করে এই ধরণের একটি উদাহরণ তৈরি করতে চাই:

Type t = typeof(Sometype);
object o = Activator.CreateInstance(t);

সাধারণত এটি কাজ করবে, তবে SomeTypeপ্যারামিটারলেস কনস্ট্রাক্টরকে সংজ্ঞায়িত না করায়, কলটি এই বার্তাটির সাথে " এই অবজেক্টের জন্য কোনও প্যারামিটারলেস কনস্ট্রাক্টর সংজ্ঞায়িত করা হবে না " Activator.CreateInstanceটাইপের ব্যতিক্রম ছুঁড়ে ফেলবে এই ধরণের উদাহরণটি তৈরি করার জন্য কি বিকল্প উপায় আছে? আমার সমস্ত ক্লাসে প্যারামিটারলেস কন্সট্রাক্টর যুক্ত করা খুব সুন্দর হবে।MissingMethodException


4
FormatterServices.GetUninitializedObjectঅবিচ্ছিন্ন স্ট্রিং তৈরি করার অনুমতি দেয় না। আপনি ব্যতিক্রম পেতে পারেন: System.ArgumentException: Uninitialized Strings cannot be created.দয়া করে এটি মনে রাখবেন।
বার্তোস্ পিয়ের্চলেউইচজ

মাথা আপ জন্য ধন্যবাদ, কিন্তু আমি ইতিমধ্যে পৃথকভাবে স্ট্রিং এবং বেসিক ধরনের পরিচালনা করছি।
আস্তিনা

উত্তর:


143

আমি এই উত্তরটি এখানে মূলত পোস্ট করেছি , তবে এখানে একটি পুনঃপ্রিন্ট হওয়ায় এটি ঠিক একই প্রশ্ন নয় তবে একই উত্তর রয়েছে:

FormatterServices.GetUninitializedObject()কনস্ট্রাক্টরকে ফোন না করেই একটি উদাহরণ তৈরি করবে create আমি এই ক্লাসটি রিফ্লেক্টর ব্যবহার করে এবং কিছু কোর। নেট সিরিয়ালাইজেশন ক্লাসের মাধ্যমে খনন করে খুঁজে পেয়েছি ।

আমি নীচের নমুনা কোডটি ব্যবহার করে এটি পরীক্ষা করেছি এবং দেখে মনে হচ্ছে এটি দুর্দান্ত কাজ করে:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Runtime.Serialization;

namespace NoConstructorThingy
{
    class Program
    {
        static void Main(string[] args)
        {
            MyClass myClass = (MyClass)FormatterServices.GetUninitializedObject(typeof(MyClass)); //does not call ctor
            myClass.One = 1;
            Console.WriteLine(myClass.One); //write "1"
            Console.ReadKey();
        }
    }

    public class MyClass
    {
        public MyClass()
        {
            Console.WriteLine("MyClass ctor called.");
        }

        public int One
        {
            get;
            set;
        }
    }
}

আশ্চর্যজনক, দেখতে আমার ঠিক এটির মতো লাগে। আমি ধরে নিই নিরবিচ্ছিন্ন মানে এর সমস্ত স্মৃতি জিরোতে সেট করা থাকবে? (স্ট্রাক্টগুলি কীভাবে ইনস্ট্যান্ট করা হয় তার
সমান

প্রতিটি ধরণের জন্য যে কোনও ডিফল্ট মানই ডিফল্ট হবে। সুতরাং অবজেক্টগুলি নাল, ইনট 0, ইত্যাদি হবে I আমি মনে করি যে কোনও শ্রেণি-স্তরের সূচনা হয় তবে কোনও নির্মাণকারী চালিত হয় না।
জেসন জ্যাকসন 3

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

21
@JSBangs FormatterServices ( msdn.microsoft.com/en-us/library/... ) অনথিভুক্ত করা হয় না।
অটোডিডাক্ট


72

ক্রিয়েটইনস্ট্যান্স পদ্ধতির এই ওভারলোডটি ব্যবহার করুন:

public static Object CreateInstance(
    Type type,
    params Object[] args
)

কনস্ট্রাক্টর ব্যবহার করে নির্দিষ্ট ধরণের একটি উদাহরণ তৈরি করে যা নির্দিষ্ট পরামিতিগুলির সাথে সর্বোত্তমভাবে মেলে।

দেখুন: http://msdn.microsoft.com/en-us/library/wcxyzt4d.aspx


4
এই সমাধানটি সমস্যাটিকে বড় করে দেখায়। আমি যদি আমার প্রকারটি না জানি এবং আমি বলছি "কেবল এই ধরণের ধরণের একটি বস্তু তৈরি করুন"?
কামি

23

যখন আমি বেঞ্চমার্ক করেছিলাম তখন এর অভিনয় (T)FormatterServices.GetUninitializedObject(typeof(T))ধীর ছিল। একই সময়ে সংকলিত এক্সপ্রেশনগুলি আপনাকে দুর্দান্ত গতি উন্নতি করতে পারে যদিও তারা কেবলমাত্র ডিফল্ট কনস্ট্রাক্টর সহ ধরণের জন্য কাজ করে। আমি একটি হাইব্রিড পদ্ধতির গ্রহণ করেছি:

public static class New<T>
{
    public static readonly Func<T> Instance = Creator();

    static Func<T> Creator()
    {
        Type t = typeof(T);
        if (t == typeof(string))
            return Expression.Lambda<Func<T>>(Expression.Constant(string.Empty)).Compile();

        if (t.HasDefaultConstructor())
            return Expression.Lambda<Func<T>>(Expression.New(t)).Compile();

        return () => (T)FormatterServices.GetUninitializedObject(t);
    }
}

public static bool HasDefaultConstructor(this Type t)
{
    return t.IsValueType || t.GetConstructor(Type.EmptyTypes) != null;
}

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

ডাকা:

MyType me = New<MyType>.Instance();

নোট যে (T)FormatterServices.GetUninitializedObject(t)স্ট্রিং জন্য ব্যর্থ হবে। সুতরাং খালি স্ট্রিং ফিরে পাওয়ার জন্য স্ট্রিংয়ের জন্য বিশেষ হ্যান্ডলিং রয়েছে।


4
কারও কোডের এক লাইনে এক নজর কীভাবে একটি দিন বাঁচাতে পারে তা অবাক করা বিষয়। ধন্যবাদ জনাব! পারফরম্যান্সের কারণগুলি আমাকে আপনার পোস্টে নিয়ে গিয়েছিল এবং কৌশলটি সম্পন্ন হয়েছে :) সংকলিত এক্সপ্রেশনগুলির তুলনায় ফর্ম্যাটর সার্ভিস এবং অ্যাক্টিভেটর ক্লাসগুলি কম পারফরম্যান্স করে চলেছে, জায়গাটির চারপাশে অ্যাক্টিভেটর খুঁজে পাওয়া একজন মমতাময়ী ব্যক্তির পক্ষে।
jmodrak

@ নওফাল স্ট্রিংয়ের জন্য আপনার বিশেষ পরিচালনা সম্পর্কে, আমি জানি যে এই বিশেষ পরিচালনা ছাড়াই স্ট্রিংয়ের জন্য এটি ব্যর্থ হবে, তবে আমি কেবল জানতে চাই: এটি কি কাজ করবে? অন্য সব ধরণের ?
Sнаđошƒаӽ

@ Sнаđошƒаӽ দুর্ভাগ্যক্রমে না। প্রদত্ত উদাহরণটি বেয়ারবোনস এবং .NET এর বিভিন্ন ধরণের প্রকার রয়েছে। উদাহরণস্বরূপ বিবেচনা করুন, আপনি যদি কোনও প্রতিনিধি পাস করেন তবে কীভাবে আপনি এটি একটি উদাহরণ দেবেন? অন্যথায় যদি কনস্ট্রাক্টর ছুড়ে ফেলে তবে আপনি এটি সম্পর্কে কী করতে পারেন? এটি পরিচালনা করার বিভিন্ন উপায়। আমার লাইব্রেরিতে আরও অনেক পরিস্থিতিতে পরিচালনা করার জন্য আমি এই আপডেটটির উত্তর দিয়েছিলাম। এটি আপাতত কোথাও প্রকাশিত নয়।
নওফাল

4

ভাল উত্তর তবে ডট নেট কমপ্যাক্ট ফ্রেমওয়ার্কে ব্যবহারযোগ্য। CF.Net এ কাজ করবে এমন একটি সমাধান এখানে ...

class Test
{
    int _myInt;

    public Test(int myInt)
    {
        _myInt = myInt;
    }

    public override string ToString()
    {
        return "My int = " + _myInt.ToString();
    }
}

class Program
{
    static void Main(string[] args)
    {
        var ctor = typeof(Test).GetConstructor(new Type[] { typeof(int) });
        var obj = ctor.Invoke(new object[] { 10 });
        Console.WriteLine(obj);
    }
}

4
এইভাবেই আমি একটি ডিফল্ট কনস্ট্রাক্টরকে কল করব। আমি নিশ্চিত না যে আমি কখনই কোনও নির্মাণকারীকে কল না করেই কোনও অবজেক্ট তৈরি করতে চাই।
ররি ম্যাকলিউড

4
আপনি যদি কাস্টম সিরিয়ালাইজার লিখছেন তবে কনস্ট্রাক্টরকে কল না করে আপনি কোনও অবজেক্ট তৈরি করতে চাইতে পারেন।
অটোডিডাক্ট

4
হ্যাঁ, এই প্রশ্নটি হ'ল সঠিক ব্যবহারের ক্ষেত্রে এটি ছিল :)
এস্টিনা

4
@ আস্তিনা সম্ভবত আপনি প্রশ্নটিতে এই তথ্য যুক্ত করতে পারেন? বেশিরভাগ লোকেরা তাদের সিটারগুলি কল না করেই বস্তু তৈরির বিরুদ্ধে থাকবে এবং আপনার সাথে এই বিষয়ে তর্ক করতে সময় লাগবে, তবে আপনার ব্যবহারের ক্ষেত্রে এটি যথার্থই প্রমাণিত হয়, তাই আমি মনে করি এটি নিজেই প্রশ্নের সাথে খুব প্রাসঙ্গিক।
জুলাইগলন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.