কোনও প্রকার নির্দিষ্ট জেনেরিক ইন্টারফেস প্রকারটি প্রয়োগ করে কিনা তা কীভাবে নির্ধারণ করবেন


226

নিম্নলিখিত ধরণের সংজ্ঞাটি ধরুন:

public interface IFoo<T> : IBar<T> {}
public class Foo<T> : IFoo<T> {}

যখন কেবল ম্যাংলেড টাইপ পাওয়া যায় তখন টাইপটি Fooজেনেরিক ইন্টারফেস প্রয়োগ করে কিনা তা আমি কীভাবে জানতে পারি IBar<T>?

উত্তর:


387

টিসিকে থেকে উত্তর ব্যবহার করে এটি নিম্নলিখিত লিনকুই কোয়েরি দিয়েও করা যেতে পারে:

bool isBar = foo.GetType().GetInterfaces().Any(x =>
  x.IsGenericType &&
  x.GetGenericTypeDefinition() == typeof(IBar<>));

1
এটি একটি খুব মার্জিত সমাধান! অন্যান্য যেগুলি আমি এসওতে দেখেছি তারা ফোরচ লুপ বা লম্বা লিনকুই কোয়েরি ব্যবহার করে। এটি ব্যবহার করার পরেও মনে রাখবেন আপনার নেট। ফ্রেমওয়ার্ক 3.5 থাকতে হবে।
ড্যানিয়েল টি।

7
আমি আপনাকে এটিকে একটি এক্সটেনশন পদ্ধতিটি বেশ বিট করার প্রস্তাব দিচ্ছি ly
ব্র্যাড হেলার

1
আপনার প্রয়োজনের উপর নির্ভর করে আপনাকে ফিরে আসা ইন্টারফেসগুলিতে পুনরাবৃত্তি করতে হবে find
সেবাস্তিয়ান গুড

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

2
গৌণ সংযোজন: আইবারের একাধিক জেনেরিক ধরণ থাকলে আপনার এই জাতীয় চিত্রগুলি বোঝাতে হবে: typeof(IBar<,,,>)স্থানধারীদের মতো কমা দিয়ে
রব ভন নেসেলরোড

33

আপনাকে উত্তরাধিকার গাছের মধ্য দিয়ে যেতে হবে এবং গাছের প্রতিটি শ্রেণীর জন্য সমস্ত ইন্টারফেসগুলি খুঁজে পেতে হবে এবং ইন্টারফেসটি জেনারিক হলেtypeof(IBar<>) কল করার ফলাফলের সাথে তুলনা করতে হবে । সব কিছু অবশ্যই বেদনাদায়ক, অবশ্যই।Type.GetGenericTypeDefinition

দেখুন এই উত্তর এবং এই বেশী আরও তথ্য এবং কোডের জন্য।


কেন শুধু আইবার <সোমক্লাস> এ নিক্ষেপ করা হবে না? (আমি অবশ্যই 'অবশ্যই' এর সাথে কাস্টিংয়ের অর্থ)
পাবলো রেটিক

5
টি অজানা এবং নির্দিষ্ট ধরণের কাস্ট করা যাবে না।
sduplooy

@ এসডুপ্লয়: সম্ভবত আমি কিছু মিস করছি যে টি কীভাবে অজানা হতে পারে? এটি পাবলিক ক্লাস ফু সংকলন করবে: IFoo <T> {}
পাবলো রেটিক

25
public interface IFoo<T> : IBar<T> {}
public class Foo : IFoo<Foo> {}

var implementedInterfaces = typeof( Foo ).GetInterfaces();
foreach( var interfaceType in implementedInterfaces ) {
    if ( false == interfaceType.IsGeneric ) { continue; }
    var genericType = interfaceType.GetGenericTypeDefinition();
    if ( genericType == typeof( IFoo<> ) ) {
        // do something !
        break;
    }
}

2
যেহেতু টাইপফ (ফু) একটি System.Type অবজেক্ট (ফু বর্ণনা করে) ফেরত দেয়, তাই getType () কলটি সর্বদা System.Type এর জন্য টাইপ ফিরিয়ে দেয়। আপনার টাইপফে (ফু) পরিবর্তন করা উচিত etGetInterfaces ()
মাইকেল মিডোস

9

একটি সহায়ক পদ্ধতি এক্সটেনশন হিসাবে

public static bool Implements<I>(this Type type, I @interface) where I : class
{
    if(((@interface as Type)==null) || !(@interface as Type).IsInterface)
        throw new ArgumentException("Only interfaces can be 'implemented'.");

    return (@interface as Type).IsAssignableFrom(type);
}

ব্যবহারের উদাহরণ:

var testObject = new Dictionary<int, object>();
result = testObject.GetType().Implements(typeof(IDictionary<int, object>)); // true!

2
"IsAssignableFrom" ছিল ঠিক কি আমি খুঁজছিলাম - ধন্যবাদ
Jesper

22
এটি জেনেরিক টাইপ প্যারামিটার না জেনে জিজ্ঞাসীর প্রয়োজনীয়তার জন্য কাজ করে না। আপনার উদাহরণ থেকে testObject.GetType ()। প্রয়োগসমূহ (টাইফফ (আইডি অভিধান <,>)); মিথ্যা ফিরে আসবে।
ctusch

@ctusch তাহলে কি এর কোন সমাধান?
তোহিদ

5

আমি @ জেনেরিক প্রোগ্রামার এক্সটেনশন পদ্ধতির কিছুটা সহজ সংস্করণ ব্যবহার করছি:

public static bool Implements<TInterface>(this Type type) where TInterface : class {
    var interfaceType = typeof(TInterface);

    if (!interfaceType.IsInterface)
        throw new InvalidOperationException("Only interfaces can be implemented.");

    return (interfaceType.IsAssignableFrom(type));
}

ব্যবহার:

    if (!featureType.Implements<IFeature>())
        throw new InvalidCastException();

5
এটি এখনও জেনেরিক ইন্টারফেসের জন্য মূল প্রশ্নের প্রয়োজনীয়তা অনুযায়ী কাজ করে না।
নাথানছেরে

4

আপনাকে জেনেরিক ইন্টারফেসের একটি নির্মিত ধরণের বিরুদ্ধে পরীক্ষা করতে হবে।

আপনাকে এরকম কিছু করতে হবে:

foo is IBar<String>

কারণ IBar<String>যে নির্মিত ধরনের প্রতিনিধিত্ব করে। আপনাকে এটি করার কারণ হ'ল কারণ যদি Tআপনার চেকটিতে অপরিজ্ঞাত থাকে তবে সংকলকটি আপনার অর্থ IBar<Int32>বা না তা জানে না IBar<SomethingElse>


4

সম্পূর্ণরূপে টাইপ সিস্টেম মোকাবেলা করার, আমি আপনাকে হ্যান্ডেল পুনরাবৃত্তির যেমন প্রয়োজন মনে IList<T>: ICollection<T>: IEnumerable<T>, যা ছাড়া আপনি কি জানেন না যে IList<int>শেষ পর্যন্ত কার্যকরী IEnumerable<>

    /// <summary>Determines whether a type, like IList&lt;int&gt;, implements an open generic interface, like
    /// IEnumerable&lt;&gt;. Note that this only checks against *interfaces*.</summary>
    /// <param name="candidateType">The type to check.</param>
    /// <param name="openGenericInterfaceType">The open generic type which it may impelement</param>
    /// <returns>Whether the candidate type implements the open interface.</returns>
    public static bool ImplementsOpenGenericInterface(this Type candidateType, Type openGenericInterfaceType)
    {
        Contract.Requires(candidateType != null);
        Contract.Requires(openGenericInterfaceType != null);

        return
            candidateType.Equals(openGenericInterfaceType) ||
            (candidateType.IsGenericType && candidateType.GetGenericTypeDefinition().Equals(openGenericInterfaceType)) ||
            candidateType.GetInterfaces().Any(i => i.IsGenericType && i.ImplementsOpenGenericInterface(openGenericInterfaceType));

    }

3

সবার আগে public class Foo : IFoo<T> {}সংকলন করা হয় না কারণ টি এর পরিবর্তে আপনার কোনও শ্রেণি নির্দিষ্ট করা দরকার, তবে ধরে নিচ্ছেন যে আপনি কিছু পছন্দ করেনpublic class Foo : IFoo<SomeClass> {}

তাহলে আপনি যদি করেন

Foo f = new Foo();
IBar<SomeClass> b = f as IBar<SomeClass>;

if(b != null)  //derives from IBar<>
    Blabla();

2

আপনি যদি একটি এক্সটেনশন পদ্ধতি চান যা জেনেরিক বেস ধরণের পাশাপাশি ইন্টারফেসগুলিকে সমর্থন করে, আমি এসডুপ্লয়ের উত্তরটি প্রসারিত করেছি:

    public static bool InheritsFrom(this Type t1, Type t2)
    {
        if (null == t1 || null == t2)
            return false;

        if (null != t1.BaseType &&
            t1.BaseType.IsGenericType &&
            t1.BaseType.GetGenericTypeDefinition() == t2)
        {
            return true;
        }

        if (InheritsFrom(t1.BaseType, t2))
            return true;

        return
            (t2.IsAssignableFrom(t1) && t1 != t2)
            ||
            t1.GetInterfaces().Any(x =>
              x.IsGenericType &&
              x.GetGenericTypeDefinition() == t2);
    }

1

প্রকারটি জেনেরিক ধরণের উত্তরাধিকার সূত্রে প্রাপ্ত বা প্রয়োগ করে কিনা তা পরীক্ষা করার পদ্ধতি:

   public static bool IsTheGenericType(this Type candidateType, Type genericType)
    {
        return
            candidateType != null && genericType != null &&
            (candidateType.IsGenericType && candidateType.GetGenericTypeDefinition() == genericType ||
             candidateType.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == genericType) ||
             candidateType.BaseType != null && candidateType.BaseType.IsTheGenericType(genericType));
    }

0

নিম্নলিখিত এক্সটেনশন চেষ্টা করুন।

public static bool Implements(this Type @this, Type @interface)
{
    if (@this == null || @interface == null) return false;
    return @interface.GenericTypeArguments.Length>0
        ? @interface.IsAssignableFrom(@this)
        : @this.GetInterfaces().Any(c => c.Name == @interface.Name);
}

এটি পরীক্ষা করার জন্য। সৃষ্টি

public interface IFoo { }
public interface IFoo<T> : IFoo { }
public interface IFoo<T, M> : IFoo<T> { }
public class Foo : IFoo { }
public class Foo<T> : IFoo { }
public class Foo<T, M> : IFoo<T> { }
public class FooInt : IFoo<int> { }
public class FooStringInt : IFoo<string, int> { }
public class Foo2 : Foo { }

এবং পরীক্ষা পদ্ধতি

public void Test()
{
    Console.WriteLine(typeof(Foo).Implements(typeof(IFoo)));
    Console.WriteLine(typeof(FooInt).Implements(typeof(IFoo)));
    Console.WriteLine(typeof(FooInt).Implements(typeof(IFoo<>)));
    Console.WriteLine(typeof(FooInt).Implements(typeof(IFoo<int>)));
    Console.WriteLine(typeof(FooInt).Implements(typeof(IFoo<string>)));
    Console.WriteLine(typeof(FooInt).Implements(typeof(IFoo<,>)));
    Console.WriteLine(typeof(FooStringInt).Implements(typeof(IFoo<,>)));
    Console.WriteLine(typeof(FooStringInt).Implements(typeof(IFoo<string,int>)));
    Console.WriteLine(typeof(Foo<int,string>).Implements(typeof(IFoo<string>)));
 }

-1

নিম্নলিখিত কোনও ভুল হওয়া উচিত নয়:

bool implementsGeneric = (anObject.Implements("IBar`1") != null);

অতিরিক্ত ক্রেডিটের জন্য আপনি যদি আপনার আইবার ক্যোয়ারির সাথে একটি নির্দিষ্ট জেনেরিক-টাইপ-প্যারামিটার সরবরাহ করতে চান তবে অ্যামবিগিউস ম্যাচএক্সেপশন ধরতে পারেন।


ভাল, সাধারণত যখন স্ট্রিংয়ের অক্ষর ব্যবহার করা সম্ভব হয় তখন এড়ানো ভাল। এই পদ্ধতিটি অ্যাপ্লিকেশনটির রিফ্যাক্টর করা আরও শক্ত করে তুলবে, যেহেতু আইবার ইন্টারফেসটির নতুন নামকরণের ফলে স্ট্রিং আক্ষরিক পরিবর্তন হবে না এবং ত্রুটিটি কেবল রানটাইমে সনাক্তকরণযোগ্য হবে।
andyroschy

আমি 'ম্যাজিক স্ট্রিংস' ইত্যাদি ব্যবহারের উপরের মন্তব্যে যতটা সম্মত হই না কেন, এটি এখনও আমার সেরা পন্থা। যথেষ্ট বন্ধ - প্রপার্টি টাইপ.নাম "আইডব্লু ওয়েভাস`1" এর সমান পরীক্ষার জন্য।
নাথানছেরে

কেন এই না? bool implementsGeneric = (anObject.Implements(typeof(IBar<>).Name) != null);
ম্যাক্সিমিম গিলিনাস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.