Câu trả lời:
Bằng cách sử dụng câu trả lời từ TcKs, nó cũng có thể được thực hiện với truy vấn LINQ sau:
bool isBar = foo.GetType().GetInterfaces().Any(x =>
x.IsGenericType &&
x.GetGenericTypeDefinition() == typeof(IBar<>));
typeof(IBar<,,,>)
với dấu phẩy đóng vai trò giữ chỗ
Bạn phải đi qua cây thừa kế và tìm tất cả các giao diện cho mỗi lớp trong cây và so sánh typeof(IBar<>)
với kết quả của việc gọi Type.GetGenericTypeDefinition
nếu giao diện là chung. Đó là tất cả một chút đau đớn, chắc chắn.
Xem câu trả lời này và những câu hỏi này để biết thêm thông tin và mã.
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;
}
}
Là một phần mở rộng phương thức trợ giúp
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);
}
Ví dụ sử dụng:
var testObject = new Dictionary<int, object>();
result = testObject.GetType().Implements(typeof(IDictionary<int, object>)); // true!
Tôi đang sử dụng một phiên bản đơn giản hơn của phương thức tiện ích mở rộng @GenericProgrammer:
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));
}
Sử dụng:
if (!featureType.Implements<IFeature>())
throw new InvalidCastException();
Bạn phải kiểm tra đối với loại được xây dựng của giao diện chung.
Bạn sẽ phải làm một cái gì đó như thế này:
foo is IBar<String>
bởi vì IBar<String>
đại diện cho loại xây dựng. Lý do bạn phải làm điều này là vì nếu T
không được xác định trong séc của bạn, trình biên dịch không biết bạn có ý IBar<Int32>
hay không IBar<SomethingElse>
.
Để giải quyết những hệ thống kiểu hoàn toàn, tôi nghĩ rằng bạn cần phải xử lý đệ quy, ví dụ IList<T>
: ICollection<T>
: IEnumerable<T>
, mà không có nó bạn sẽ không biết rằng IList<int>
cuối cùng cụ 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));
}
Trước hết public class Foo : IFoo<T> {}
không biên dịch vì bạn cần chỉ định một lớp thay vì T, nhưng giả sử bạn làm một cái gì đó nhưpublic class Foo : IFoo<SomeClass> {}
sau đó nếu bạn làm
Foo f = new Foo();
IBar<SomeClass> b = f as IBar<SomeClass>;
if(b != null) //derives from IBar<>
Blabla();
Trong trường hợp bạn muốn một phương thức mở rộng hỗ trợ các loại cơ sở chung cũng như giao diện, tôi đã mở rộng câu trả lời của sduploo:
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);
}
Phương pháp kiểm tra xem kiểu kế thừa hay thực hiện kiểu chung:
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));
}
Hãy thử phần mở rộng sau đây.
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);
}
Để kiểm tra nó. tạo nên
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 { }
và phương pháp thử
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>)));
}
Không nên có bất cứ điều gì sai sau đây:
bool implementsGeneric = (anObject.Implements("IBar`1") != null);
Để có thêm tín dụng, bạn có thể bắt gặp AmbiguptMatchException nếu bạn muốn cung cấp một tham số loại chung cụ thể với truy vấn IBar của mình.
bool implementsGeneric = (anObject.Implements(typeof(IBar<>).Name) != null);