কোনও প্রকার সি # প্রতিবিম্ব সহ একটি ইন্টারফেস প্রয়োগ করে কিনা তা কীভাবে নির্ধারণ করবেন


561

না প্রতিফলন মধ্যে C#যদি কিছু দেওয়া নির্ধারণ অফার একটি উপায় System.Typeটাইপ মডেল কিছু ইন্টারফেস?

public interface IMyInterface {}

public class MyType : IMyInterface {}

// should yield 'true'
typeof(MyType)./* ????? */MODELS_INTERFACE(IMyInterface);

উত্তর:


968

আপনার কয়েকটি পছন্দ আছে:

  1. typeof(IMyInterface).IsAssignableFrom(typeof(MyType))

  2. typeof(MyType).GetInterfaces().Contains(typeof(IMyInterface))

জেনেরিক ইন্টারফেসের জন্য এটি কিছুটা আলাদা।

typeof(MyType).GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IMyInterface<>))

68
এই টাইফফটি (আইএমআইআইন্টারফেস) মনে রাখবেন .আইএসএসাইনএবলফ্রোম (টাইপফ (আইএমআইআইন্টারফেস)) সত্য, যা আপনার কোডে একটি অপ্রত্যাশিত ফলাফল হতে পারে।
ক্রিস কেম্প

29
এটা নিশ্চিত যে মনোযোগ না দেওয়া এবং IsAssignableFromপিছনের দিকে যুক্তিগুলি পাওয়া সহজ ছিল । আমি GetInterfacesএখনই যাব : পি
বেঞ্জামিন

12
IsAssignableFrom(t1)বৈকল্পিক যতো তাড়াতাড়ি 3x সম্পর্কে GetInterfaces().Contains(t2)আমার কোডে সহযোগীর।
পিয়ের আরনাড 15'13

24
@ পিয়ারআরনাড: ইসএইসিনেবলফ্রমে অবশেষে গেটইন্টারফেসগুলি কল করে, তাই সম্ভবত আপনার পরীক্ষাটি প্রথমে গেটইন্টারফেসগুলি পরীক্ষা করে এবং এর পরে ইসএইসনেবলযোগ্য। এটি হ'ল কারণ গেটইন্টারফেসগুলি এর ফলাফলগুলি ক্যাশে করে তাই প্রথম
আহবানটির

17
@ কোস্টার উত্তরে একটি ছোট্ট পরিবর্তন। সি # 6 দিয়ে আমরা typeof(MyType).GetInterface(nameof(IMyInterface)) != nullআরও ভাল ধরণের সুরক্ষা এবং রিফ্যাক্টরিংয়ের জন্য করতে পারি ।
অহলমস


32
typeof(IMyInterface).IsAssignableFrom(someclass.GetType());

অথবা

typeof(IMyInterface).IsAssignableFrom(typeof(MyType));

34
যদি আপনার কাছে ইতিমধ্যে ক্লাসের উদাহরণ রয়েছে তবে আরও ভাল পদ্ধতির মধ্যে কেবল someclass is IMyInterfaceপ্রতিচ্ছবি ব্যয় জড়িত না। সুতরাং, ভুল না হলেও এটি এটি করার আদর্শ উপায় নয়।
জেমস জে। রেগান চতুর্থ

1
@ জামেস - সম্মত হন। এমনকি রিশার্পারও একই পরামর্শ দেয়।
আংশুমন আগরওয়াল

@ জেমসজেগ। রিগ্রানইভ আপনার পোস্ট করা উচিত উত্তর হিসাবে, আমি আপনার মন্তব্য প্রায় মিস করেছি
রেগেইগুইটার

@reggaeguitar, ধন্যবাদ, কিন্তু মন্তব্যটি মূল প্রশ্নের উত্তর দেয় না। প্রশ্নটি প্রতিবিম্ব সমাধানের জন্য জিজ্ঞাসা করে, আমি কেবল এই উত্তরের প্রথম ক্ষেত্রে বলছি যেখানে আপনার কাছে প্রতিচ্ছবি প্রতিচ্ছবি হওয়ার উদাহরণ রয়েছে তা আদর্শ সমাধান নয়।
জেমস জে। রেগান চতুর্থ

1
@ জেমসজে.আগ্রানভ আসলে, isউত্তরাধিকার শ্রেণিবিন্যাসের উভয় দিক IsAssignableFromযাচাই করে তবে কেবল উপরের দিকে পরীক্ষা করে। এছাড়াও, যদি আপনার কোনও জিনিসের উদাহরণ থাকে তবে আপনার কল করা উচিত IsInstanceOfType(যা কেবল উপরের দিকেও দেখায়)।
সেলোরিও

13
public static bool ImplementsInterface(this Type type, Type ifaceType) 
{
    Type[] intf = type.GetInterfaces();
    for(int i = 0; i < intf.Length; i++) 
    {
        if(intf[ i ] == ifaceType) 
        {
            return true;
        }
    }
    return false;
}

আমি মনে করি এটি সঠিক কারণ, তিনটি কারণে:

  1. এটি GetInterfaces ব্যবহার করে, ISAssignableFrom নয়, শেষ পর্যন্ত বেশ কয়েকটি পরীক্ষার পরে getInterfaces কল করার পরে IsAssignableFrom থেকে এটি দ্রুততর হয়।
  2. এটি স্থানীয় অ্যারেতে পুনরাবৃত্তি করে, সুতরাং কোনও সীমানা পরীক্ষা করা হবে না।
  3. এটি == অপারেটরটি ব্যবহার করে যা প্রকারের জন্য সংজ্ঞায়িত, সুতরাং সম্ভবত সমান পদ্ধতির চেয়ে নিরাপদ (এটি ধারণ করে যে কলগুলি অন্তর্ভুক্ত ব্যবহার করবে) than

10
সামগ্রীর জন্য +1, যদিও আমি পেরেন এবং মিশরীয় ধনুর্বন্ধনী এর চারপাশের স্পেসগুলি ঘৃণা করি। এছাড়াও পুরো পদ্ধতিটি এইভাবে লেখা যেতে পারে: রিটার্ন টাইপ etGetInterfaces () Any যে কোনও (t => t == ifaceType);
রেগেগুইটার

1
Type.IsAssignableFrom () ইন্টারনালি ঠিক আপনার কোডের মতো কাজ করে
devi

1
এছাড়াও কেন টাইপ করবেন না etGETInterfaces () Cont থাকে (ifaceType) যা LINQ ব্যবহার করে না।

9

আমি করেছি:

public static bool Implements<I>(this Type source) where I : class
{
  return typeof(I).IsAssignableFrom(source);
}

আমি যদি বলতে পারতাম where I : interfaceতবে interfaceজেনেরিক প্যারামিটার সীমাবদ্ধতা বিকল্প নয়। classএটি যতটা কাছে আসে তত কাছাকাছি।

ব্যবহার:

if(MyType.Implements<IInitializable>())
  MyCollection.Initialize();

আমি কেবল বলেছি Implementsকারণ এটি আরও স্বজ্ঞাত। আমি সবসময় IsAssignableFromফ্লিপ-ফ্লপ হয়ে যাই ।


return typeof(I).IsInterface && typeof(I).IsAssignableFrom(source);পদ্ধতির কোনও 'ভুল' ব্যবহারের ক্ষেত্রে আপনি মিথ্যা ফিরিয়ে দিতে পারেন, এটি; এটি একটি ইন্টারফেস টাইপের পরিবর্তে শ্রেণির ধরণের সাথে ব্যবহার করে, বিকল্প-পরামিতি যদি ইন্টারফেস না হয় তবে বিকল্পভাবে একটি ব্যতিক্রম ছুঁড়ে দিন। যদিও আপনি তর্ক করতে পারেন যে একটি উত্পন্ন শ্রেণি তার পিতামাতাকে 'প্রয়োগ' করে ...
সিন্ধ্রি জেলসন

7

অনুকূল পারফরম্যান্সের জন্য জেফের উত্তরটি সংশোধন করা (পিয়ের আরনাডের পারফরম্যান্স পরীক্ষার জন্য ধন্যবাদ):

var type = typeof(MyType);
var implementsInterface = typeof(IMyInterface).IsAssignableFrom(type) && type.IsClass;

প্রদত্ত একটি ইন্টারফেস কার্যকর করে এমন সমস্ত ধরণের সন্ধান করতে Assembly:

var implementations = typeof(TypeInTargetAssembly).Assembly.GetTypes()
                          .Where(t => typeof(IMyInterface).IsAssignableFrom(t) && t.IsClass);

7

যেমন অন্য কেউ ইতিমধ্যে উল্লেখ করেছেন: বেঞ্জামিন এপ্রিল 10 '13 এ 22:21 "

মনোযোগ না দেওয়া এবং ইসএসাইনেবলফর্মের জন্য পিছনের দিকে যুক্তিগুলি পাওয়া সহজ ছিল sure আমি এখনই গেটইন্টারফেসগুলি নিয়ে যাব: পি -

ঠিক আছে, অন্য উপায়টি হ'ল একটি সংক্ষিপ্ত সম্প্রসারণ পদ্ধতিটি তৈরি করা যা কিছুটা হলেও, "সর্বাধিক স্বাভাবিক" চিন্তাভাবনার পদ্ধতিটি (এবং একমত হয়েছে যে এটি নিজের পছন্দগুলির উপর ভিত্তি করে কিছুটা "প্রাকৃতিক" করার জন্য এটি একটি খুব সামান্য ব্যক্তিগত পছন্দ ):

public static class TypeExtensions
{
    public static bool IsAssignableTo(this Type type, Type assignableType)
    {
        return assignableType.IsAssignableFrom(type);
    }
}

এবং কেন আরও কিছু জেনেরিক না যাচ্ছেন (এটি সত্যিই আকর্ষণীয় কিনা তা নিশ্চিত নয়, ভাল আমি ধরে নিচ্ছি যে আমি কেবল 'সিনট্যাক্সিং' চিনির আরও একটি চিমটি পার করছি):

public static class TypeExtensions
{
    public static bool IsAssignableTo(this Type type, Type assignableType)
    {
        return assignableType.IsAssignableFrom(type);
    }

    public static bool IsAssignableTo<TAssignable>(this Type type)
    {
        return IsAssignableTo(type, typeof(TAssignable));
    }
}

আমি মনে করি এটি সেভাবে অনেক বেশি প্রাকৃতিক হতে পারে তবে এটি আবার খুব ব্যক্তিগত মতামতের বিষয়:

var isTrue = michelleType.IsAssignableTo<IMaBelle>();

4
আপনি কেবল এক্সটেনশন পদ্ধতিতে বাস্তবায়ন সরাসরি স্থাপন না করার কোনও কারণ আছে? আমি নিশ্চিত যে এটি আপনাকে উভয় উপায়ে কল করতে দেয় তবে আপনি কেন কখনও এটি করার প্রয়োজন হবে?
মার্ক এ। ডোনোহো

@ মার্কিআইভি আপনার কাছে প্রায় 2 বছর দেরীতে ফিরে আসার জন্য দুঃখিত, ভাল আমার ধারণা যে পুনরাবৃত্তি কোডটি এড়ানোর জন্য এক্সটেনশন পদ্ধতিতে সাহায্যকারী পদ্ধতিটি लपेटানো আমার পুরানো খারাপ অভ্যাস ছিল, আমার উত্তরটি সম্পাদনা করবে :)
কেরি পেরেট

1
@ মার্কিআইভিও সম্পন্ন প্লাস আমার অন্যান্য খারাপ অভ্যাসটি পরিবর্তিত করেছে যার নাম নেই, যেমন Boolean => bool(আমি যখন ছোট ছিলাম তখন কোডিংয়ের কিছু কঠোর "অভিনব" নিয়ম কেন ব্যবহার করতাম) না)
কেরি পেরেট

3

আপনার যদি কোনও টাইপ বা উদাহরণ থাকে তবে আপনি সহজেই পরীক্ষা করতে পারেন তারা কোনও নির্দিষ্ট ইন্টারফেস সমর্থন করে কিনা।

কোনও বস্তু একটি নির্দিষ্ট ইন্টারফেস প্রয়োগ করে কিনা তা পরীক্ষা করতে:

if(myObject is IMyInterface) {
  // object myObject implements IMyInterface
}

কোনও টাইপ একটি নির্দিষ্ট ইন্টারফেস প্রয়োগ করে কিনা তা পরীক্ষা করতে:

if(typeof(IMyInterface).IsAssignableFrom(typeof(MyType))) {
  // type MyType implements IMyInterface
}

আপনি যদি জেনেরিক কোনও জিনিস পেয়ে থাকেন এবং একটি aালাই করতে চান এবং সেই সাথে আপনার পরীক্ষা করা ইন্টারফেসটি কোডটি প্রয়োগ করা হয়েছে কিনা তা পরীক্ষা করে দেখুন:

 var myCastedObject = myObject as IMyInterface;

    if(myCastedObject != null) {
      // object myObject implements IMyInterface
    }

2

IsAssignableFromএখন সরানো হয়েছে TypeInfo:

typeof(ISMSRequest).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo());

1

এর জন্য অনুসন্ধান করা যে কোনও ব্যক্তিকে নিম্নলিখিত এক্সটেনশন পদ্ধতিটি দরকারী হতে পারে:

public static class TypeExtensions
{
    public static bool ImplementsInterface(this Type type, Type @interface)
    {
        if (type == null)
        {
            throw new ArgumentNullException(nameof(type));
        }

        if (@interface == null)
        {
            throw new ArgumentNullException(nameof(@interface));
        }

        var interfaces = type.GetInterfaces();
        if (@interface.IsGenericTypeDefinition)
        {
            foreach (var item in interfaces)
            {
                if (item.IsConstructedGenericType && item.GetGenericTypeDefinition() == @interface)
                {
                    return true;
                }
            }
        }
        else
        {
            foreach (var item in interfaces)
            {
                if (item == @interface)
                {
                    return true;
                }
            }
        }

        return false;
    }
}

xunit পরীক্ষা:

public class TypeExtensionTests
{
    [Theory]
    [InlineData(typeof(string), typeof(IList<int>), false)]
    [InlineData(typeof(List<>), typeof(IList<int>), false)]
    [InlineData(typeof(List<>), typeof(IList<>), true)]
    [InlineData(typeof(List<int>), typeof(IList<>), true)]
    [InlineData(typeof(List<int>), typeof(IList<int>), true)]
    [InlineData(typeof(List<int>), typeof(IList<string>), false)]
    public void ValidateTypeImplementsInterface(Type type, Type @interface, bool expect)
    {
        var output = type.ImplementsInterface(@interface);
        Assert.Equal(expect, output);
    }
}

0

কি সম্পর্কে

if(MyType as IMyInterface != null)

?


4
আমার কাছে একটি উদাহরণ থাকলে এটি সুস্পষ্ট। প্রতিবিম্ব থেকে যখন আমার কাছে কোনও প্রকার থাকে তখন কার্যকর হয় না
edc65


0

একটি সঠিক উত্তর

typeof(MyType).GetInterface(nameof(IMyInterface)) != null;

যাহোক,

typeof(MyType).IsAssignableFrom(typeof(IMyInterface));

নিম্নলিখিত কোডটি স্ট্রিং এবং আইকনভার্টেবলের সাথে প্রদর্শিত হওয়ায় কোনও ভুল ফলাফল আসতে পারে:

    static void TestIConvertible()
    {
        string test = "test";
        Type stringType = typeof(string); // or test.GetType();

        bool isConvertibleDirect = test is IConvertible;
        bool isConvertibleTypeAssignable = stringType.IsAssignableFrom(typeof(IConvertible));
        bool isConvertibleHasInterface = stringType.GetInterface(nameof(IConvertible)) != null;

        Console.WriteLine($"isConvertibleDirect: {isConvertibleDirect}");
        Console.WriteLine($"isConvertibleTypeAssignable: {isConvertibleTypeAssignable}");
        Console.WriteLine($"isConvertibleHasInterface: {isConvertibleHasInterface}");
    }

ফলাফল:

 isConvertibleDirect: True
 isConvertibleTypeAssignable: False
 isConvertibleHasInterface: True

4
আপনি যেমন স্বীকৃত উত্তরে দেখতে পাচ্ছেন, আপনি ব্যবহারের ধরণগুলিতে আন্তঃসংযোগ করেছেন IsAssignableFrom। ঠিক যেমন বেনিয়ামিন এবং এহোর্ন সতর্কতার বিষয়ে।
ভিভি 5198722

0

মনে রাখবেন যে আপনার যদি জেনেরিক ইন্টারফেস থাকে IMyInterface<T>তবে এটি সর্বদা ফিরে আসবে false:

  typeof(IMyInterface<>).IsAssignableFrom(typeof(MyType)) /* ALWAYS FALSE */

এটিও কাজ করে না:

  typeof(MyType).GetInterfaces().Contains(typeof(IMyInterface<>))  /* ALWAYS FALSE */

যাইহোক, যদি MyTypeকার্যকরী IMyInterface<MyType>এই কাজ করে এবং আয় true:

  typeof(IMyInterface<MyType>).IsAssignableFrom(typeof(MyType))

তবে আপনি Tরানটাইমে টাইপ প্যারামিটারটি জানেন না । কিছুটা হ্যাকি সমাধান হ'ল:

  typeof(MyType).GetInterfaces()
                .Any(x=>x.Name == typeof(IMyInterface<>).Name)

জেফের সমাধানটি কিছুটা কম

  typeof(MyType).GetInterfaces()
         .Any(i => i.IsGenericType 
             && i.GetGenericTypeDefinition() == typeof(IMyInterface<>));

Typeযে কোনও ক্ষেত্রে এটির জন্য একটি এক্সটেনশন পদ্ধতি এখানে রয়েছে :

public static class TypeExtensions
{
    public static bool IsImplementing(this Type type, Type someInterface)
    {
        return type.GetInterfaces()
             .Any(i => i == someInterface 
                 || i.IsGenericType 
                    && i.GetGenericTypeDefinition() == someInterface);
    }
}

(নোট করুন যে উপরেরগুলিতে লিনাক ব্যবহার করা হয়েছে যা সম্ভবত লুপের চেয়ে ধীর)

তারপরে আপনি এটি করতে পারেন:

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