c# - কিভাবে জেনারিক ক্লাস বা পদ্ধতির সদস্য থেকে টি টাইপ পেতে?




.net generics (12)

(নোট: আমি অনুমান করছি যে আপনি যা জানেন তা object বা IList বা অনুরূপ, এবং যে তালিকা রানটাইম এ কোনও ধরনের হতে পারে)

যদি আপনি এটি একটি List<T> , তাহলে:

Type type = abc.GetType().GetGenericArguments()[0];

আরেকটি বিকল্প সূচী তাকান হয়:

Type type = abc.GetType().GetProperty("Item").PropertyType;

নতুন টাইপইনফো ব্যবহার করে:

using System.Reflection;
// ...
var type = abc.GetType().GetTypeInfo().GenericTypeArguments[0];

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

public class Foo<T>
{
    public List<T> Bar { get; set; }

    public void Baz()
    {
        // get type of T
    }   
}

যখন আমি ক্লাসটি তাত্ক্ষণিক করি, MyTypeObject1 হয়ে যায়, তাই শ্রেণির একটি সাধারণ তালিকা রয়েছে: List<MyTypeObject1> । এটি একটি জেনারিক পদ্ধতিতে একটি জেনারিক পদ্ধতিতে প্রযোজ্য:

public class Foo
{
    public void Bar<T>()
    {
        var baz = new List<T>();

        // get type of T
    }
}

আমি জানতে চাই, আমার ক্লাসের তালিকায় কী ধরনের বস্তু রয়েছে। সুতরাং তালিকাভুক্ত সম্পত্তি তালিকা Bar বা স্থানীয় পরিবর্তনশীল baz , T কি ধরনের থাকে?

আমি Bar[0].GetType() করতে পারি না Bar[0].GetType() , কারণ তালিকায় শূন্য উপাদান থাকতে পারে। আমি এটা কিভাবে করবো?


3dGrabber এর সমাধান ব্যবহার করে:

public static T GetEnumeratedType<T>(this IEnumerable<T> _)
{
    return default(T);
}

//and now 

var list = new Dictionary<string, int>();
var stronglyTypedVar = list.GetEnumeratedType();

আপনি যদি সম্পত্তিটির অন্তর্নিহিত প্রকারটি জানতে চান তবে এটি চেষ্টা করুন:

propInfo.PropertyType.UnderlyingSystemType.GenericTypeArguments[0]

আপনি যে কোন সংগ্রহের ধরন থেকে "টি" টাইপটি পেতে পারেন যা নিখরচায় <T> প্রয়োগ করে নিম্নলিখিতগুলি প্রয়োগ করে:

public static Type GetCollectionItemType(Type collectionType)
{
    var types = collectionType.GetInterfaces()
        .Where(x => x.IsGenericType 
            && x.GetGenericTypeDefinition() == typeof(IEnumerable<>))
        .ToArray();
    // Only support collections that implement IEnumerable<T> once.
    return types.Length == 1 ? types[0].GetGenericArguments()[0] : null;
}

উল্লেখ্য যে এটি এমন ধরনের সংগ্রহগুলির সমর্থন করে না যা IENumerable <T> দুইবার প্রয়োগ করে, যেমন

public class WierdCustomType : IEnumerable<int>, IEnumerable<string> { ... }

আমি আপনাকে সমর্থন করার প্রয়োজন হলে আপনি একটি অ্যারের ধরনের ফিরে আসতে পারে অনুমান ...

এছাড়াও, যদি আপনি এটি অনেকগুলি করছেন (উদাহরণস্বরূপ একটি লুপে) প্রতি সংগ্রহের ফলাফলের ফলাফলটি ক্যাশ করতে চান।


এই আমি এটা কিভাবে

internal static Type GetElementType(this Type type)
{
        //use type.GenericTypeArguments if exist 
        if (type.GenericTypeArguments.Any())
         return type.GenericTypeArguments.First();

         return type.GetRuntimeProperty("Item").PropertyType);
}

তারপর এই মত কল

var item = Activator.CreateInstance(iListType.GetElementType());

অথবা

var item = Activator.CreateInstance(Bar.GetType().GetElementType());

এটা আমার জন্য কাজ। যেখানে MyList কিছু অজ্ঞাত ধরনের তালিকা।

IEnumerable myEnum = myList as IEnumerable;
Type entryType = myEnum.AsQueryable().ElementType;

চেষ্টা

list.GetType().GetGenericArguments()

ডেভেলপারদের জন্য যারা টাইপের নামের সাথে আক্ষরিক অর্থে মোকাবিলা করতে চায়, উদাহরণস্বরূপ একটি সুইচ বিবৃতি ব্যবহার করার জন্য, এখানে একটি উদাহরণ দেওয়া হল:

    public static void TypeBasedLogic<T>(T item)
    {
        switch (typeof(T).ToString()) //e.g. System.Int32
        {
            case nameof(System) + "." + nameof(Int32):
                //Logic for int
                Console.Write("It's an integer");
            break;

            case nameof(System) + "." + nameof(Double):
                //Logic for double
                Console.Write("It's a double");
            break;

            case nameof(System) + "." + nameof(Decimal):
                //Logic for decimal
                Console.Write("It's a decimal");
            break;

            case nameof(System) + "." + nameof(String):
                //Logic for string
                Console.Write("It's a string");
            break;

            default:
                //logic for the rest other System or custom types
                Console.Write("It's a "+ typeof(T).ToString());
            break;

        }
    }

ব্যবহার:

TypeBasedLogic(5); // outputs: It's an integer

নিম্নলিখিত এক্সটেনশন পদ্ধতির সাথে আপনি প্রতিফলন ছাড়া দূরে পেতে পারেন:

public static Type GetListType<T>(this List<T> _)
{
    return typeof(T);
}

অথবা আরো সাধারণ:

public static Type GetEnumeratedType<T>(this IEnumerable<T> _)
{
    return typeof(T);
}

ব্যবহার:

List<string>        list    = new List<string> { "a", "b", "c" };
IEnumerable<string> strings = list;
IEnumerable<object> objects = list;

Type listType    = list.GetListType();           // string
Type stringsType = strings.GetEnumeratedType();  // string
Type objectsType = objects.GetEnumeratedType();  // BEWARE: object

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

T checkType = default(T);

if (checkType is MyClass)
{}

GetGenericArgument() পদ্ধতিটি আপনার ইনস্ট্যান্সের বেস GetGenericArgument() নির্ধারণ করতে হবে (যার শ্রেণী একটি জেনেরিক ক্লাস myClass<T> )। অন্যথায়, এটি একটি টাইপ [0]

উদাহরণ:

Myclass<T> instance = new Myclass<T>();
Type[] listTypes = typeof(instance).BaseType.GetGenericArguments();

public bool IsCollection<T>(T value){
  var valueType = value.GetType();
  return valueType.IsArray() || typeof(IEnumerable<object>).IsAssignableFrom(valueType) || typeof(IEnumerable<T>).IsAssignableFrom(valuetype);
}




generics