সি # জেনেরিক পরামিতি হিসাবে System.Type ব্যবহার করুন


89

আমার কাছে টাইপগুলির একটি (সিস্টেম.টাইপ) রয়েছে যা ডাটাবেসে অনুসন্ধান করা দরকার।

এই প্রতিটি ধরণের জন্য, আমাকে নিম্নলিখিত এক্সটেনশনমিডুড (যা লিনকটোনাবার্টের অংশ) কল করতে হবে:

Session.Linq<MyType>()

তবে আমার কাছে মাইটাইপ নেই, তবে আমি পরিবর্তে কোনও প্রকার ব্যবহার করতে চাই।

আমার যা আছে তা হ'ল:

System.Type typeOne;

তবে আমি নিম্নলিখিতগুলি সম্পাদন করতে পারি না:

Session.Linq<typeOne>()

জেনেরিক প্যারামিটার হিসাবে আমি কোনও প্রকারটি কীভাবে ব্যবহার করতে পারি?

উত্তর:


95

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

প্রতিবিম্বের মাধ্যমে আপনাকে পদ্ধতিটি কল করতে হবে - এরকম কিছু:

// Get the generic type definition
MethodInfo method = typeof(Session).GetMethod("Linq", 
                                BindingFlags.Public | BindingFlags.Static);

// Build a method with the specific type argument you're interested in
method = method.MakeGenericMethod(typeOne);
// The "null" is because it's a static method
method.Invoke(null, arguments);

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


4
আমি এমন একটি সমাধান সম্পর্কে পড়েছি যা পদ্ধতিটি কল করার জন্য প্রতিবিম্ব ব্যবহার করে। তবে আমি আশা করি এর আরও একটি সমাধান রয়েছে।
জানুয়ারী

অনুরোধ পদ্ধতিটি একটি "অবজেক্ট" প্রদান করে। আমি সঠিকভাবে এটি টাইপ না করা পর্যন্ত আমি এই বস্তুটিতে কোয়েরি করতে সক্ষম নই। (যা সম্ভবত আইকোয়্যারেবল <T> হবে)। আমি কীভাবে এই জিনিসটিকে আমার ধরণে ফেলে দিতে পারি?
জানুয়ারী

4
@ জ্যান: আপনি পারবেন না - তবে আপনি সেই ধরণটি আর ব্যবহার করতে পারবেন না, কারণ আপনি সংকলনকালে টাইপটি জানেন না ... এটি এখানেই জেনেরিক পদ্ধতি লেখার পক্ষে আপনার পক্ষে মূল্যবান হতে পারে আপনি যা চান তা সবই দৃ strongly়-টাইপযুক্ত পদ্ধতিতে করে এবং এটি প্রতিচ্ছবি সহ কল করে । বিকল্পভাবে, নন-জেনেরিকগুলি IQueryableআপনার যা প্রয়োজন তা করে?
জন স্কিটি

4
@ জন: ধন্যবাদ, আমি আমার নিজের জেনেরিক পদ্ধতিটি লেখার চেষ্টা করব। দুর্ভাগ্যক্রমে নন-জেনেরিক আইকোয়্যারেবল সমস্যার সমাধান করবে না।
জানুয়ারী

4
@Jon: আমার নিজের জেনেরিক পদ্ধতির সাহায্যে আরেকটি জেনেরিক পদ্ধতি ডাকতে সমস্যার সমাধান
জানুয়ারী

30

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

typeof(Session).GetMethod("Linq").MakeGenericMethod(typeOne).Invoke(null, null);

(ধরে নিচ্ছি যে Linq<T>()এটি ধরণের একটি স্থির পদ্ধতি Session)

যদি Sessionআসলে কোনও বস্তু হয় তবে আপনাকে Linqপদ্ধতিটি আসলে কোথায় ঘোষিত হয়েছে তা জানতে হবে এবং Sessionযুক্তি হিসাবে প্রবেশ করতে হবে :

typeof(DeclaringType).GetMethod("Linq").MakeGenericMethod(typeOne)
     .Invoke(null, new object[] {Session});

1

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

/// <summary>
    /// This method call your method through Reflection 
    /// so i wil call the method like CallGenericMethodThroughReflection<Session>(assemblyQualifiedName,Linq,false,new[] { file }) 
    /// </summary>
    /// <typeparam name="T">Call method from which file</typeparam>
    /// <param name="assemblyQualifiedName">Your can get assemblyQualifiedName like typeof(Payroll.Domain.Attendance.AttendanceApplicationMaster).AssemblyQualifiedName</param>
    /// <param name="methodName"></param>
    /// <param name="isStaticMethod"></param>
    /// <param name="paramaterList"></param>
    /// <param name="parameterType">pass parameter type list in case of the given method have overload  </param>
    /// <returns>return object of calling method</returns>
    public static object CallGenericMethodThroughReflection<T>(string assemblyQualifiedName, string methodName,bool isStaticMethod ,object[] paramaterList,Type[] parameterType = null)
    {
        try
        {
            object instance = null;
            var bindingAttr = BindingFlags.Static | BindingFlags.Public;
            if (!isStaticMethod)
            {
                instance = Activator.CreateInstance<T>();
                bindingAttr = BindingFlags.Instance | BindingFlags.Public;
            }
            MethodInfo MI = null;
            var type = Type.GetType(assemblyQualifiedName);
            if(parameterType == null)
                MI = typeof(T).GetMethod(methodName, bindingAttr);
            else
                MI = typeof(T).GetMethod(methodName, bindingAttr,null, parameterType, null);//this will work in most case some case not work
            if (type == null || MI == null) // if the condition is true it means given method or AssemblyQualifiedName entity not found
                return null;
            var genericMethod = MI.MakeGenericMethod(new[] { type });
            return genericMethod.Invoke(instance, paramaterList);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.