जवाबों:
TcK से उत्तर का उपयोग करके यह निम्नलिखित LINQ क्वेरी के साथ भी किया जा सकता है:
bool isBar = foo.GetType().GetInterfaces().Any(x =>
x.IsGenericType &&
x.GetGenericTypeDefinition() == typeof(IBar<>));
typeof(IBar<,,,>)
प्लेसहोल्डर्स की तरह अल्पविराम अभिनय के साथ
आपको वंशानुक्रम वृक्ष के माध्यम से ऊपर जाना होगा और पेड़ में प्रत्येक वर्ग के लिए सभी इंटरफेस खोजने होंगे, और यदि इंटरफ़ेस सामान्य है तोtypeof(IBar<>)
कॉलिंग के परिणाम की तुलना करें । यह सब थोड़ा दर्दनाक है, निश्चित रूप से।Type.GetGenericTypeDefinition
देखें क्या यह उत्तर और इन लोगों को अधिक जानकारी और कोड के लिए।
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;
}
}
एक सहायक विधि विस्तार के रूप में
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!
मैं @GenericProgrammers एक्सटेंशन विधि का थोड़ा सरल संस्करण उपयोग कर रहा हूं:
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();
आपको जेनेरिक इंटरफ़ेस के निर्माण प्रकार के खिलाफ जांच करनी होगी।
आपको कुछ इस तरह करना होगा:
foo is IBar<String>
क्योंकि IBar<String>
उस प्रकार का प्रतिनिधित्व करता है। ऐसा करने का कारण यह है कि यदि T
आपके चेक में अपरिभाषित है, तो संकलक को पता नहीं है कि आपका क्या मतलब है IBar<Int32>
या IBar<SomethingElse>
।
पूरी तरह से प्रकार प्रणाली से निपटने के लिए, मैं तुम्हें संभाल प्रत्यावर्तन, जैसे की जरूरत है लगता है IList<T>
: ICollection<T>
: IEnumerable<T>
, जिसके बिना आप नहीं जानते हैं कि IList<int>
अंततः औजार IEnumerable<>
।
/// <summary>Determines whether a type, like IList<int>, implements an open generic interface, like
/// IEnumerable<>. 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));
}
सबसे पहले 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();
यदि आप एक विस्तार विधि चाहते हैं जो सामान्य आधार प्रकारों के साथ-साथ इंटरफेस का समर्थन करेगी, तो मैंने sduplooy के उत्तर का विस्तार किया है:
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);
}
यह जाँचने का तरीका कि क्या प्रकार विरासत में मिलता है या लागू होता है:
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));
}
निम्नलिखित विस्तार का प्रयास करें।
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>)));
}
निम्नलिखित में कुछ भी गलत नहीं होना चाहिए:
bool implementsGeneric = (anObject.Implements("IBar`1") != null);
अतिरिक्त क्रेडिट के लिए आप AmbiguousMatchException को पकड़ सकते हैं यदि आप अपने IBar क्वेरी के साथ एक विशिष्ट सामान्य-प्रकार-पैरामीटर प्रदान करना चाहते हैं।
bool implementsGeneric = (anObject.Implements(typeof(IBar<>).Name) != null);