2

I have seen answers on SO with similar questions but did not find one addressing all criteria below.

How can I determine whether class B meets the following criteria when B inherits from A:

  • [B] does not implement any [additional] interfaces (generic or not).
  • [A] implements a generic interface with its own type as the generic parameter?

The following

object o = new SomeObject();
bool result = (o.GetType().GetInterfaces()[0] == typeof(IKnownInterface<???>));
// ??? should be typeof(o). How to achieve this?

I know I can get the interface name string from the type which is something like "NameSpace.ClassName+IKnownInterface'1[[SomeType, ModuleName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]" but this does not seem intuitive or safe. Plus the '1 notation is incremental based on the number of generic types used for that interface.

I am either going about this the wrong way or missing something silly here. Please advise.

Raheel Khan
  • 14,205
  • 13
  • 80
  • 168
  • 1
    If `B` inherits from `A` it's *impossible* for `A` to implement an interface and `B` to not. `B`, by definition, implements all interfaces `A` does. – Servy May 13 '13 at 17:51
  • I'll update my question. What I meant was that B does not implement any additional interfaces that A does not have. – Raheel Khan May 13 '13 at 17:55
  • Can you explain _why_ you'd want to check your devs like that? Unit tests should point at black boxes, the implementation shouldn't matter. Consider the example of an `IEmailer` which is internally instantiated from a factory which requires `IInstantiable` (contrived I know but...). As long as it works as an IEmailer, why do you care what else it is? You're attempting to unit test the implementation not the functionality – Basic May 13 '13 at 19:03
  • @Basic: Unit tests may not be the ideal way to enforce this but it sure is convenient. In my scenario, I have some important classes that have an extremely narrow scope and should not be doing anything besides they are expected to do. In other words, small liberties taken by developers can potentially break the system. This is one of many simple pre-quality-control checks we have for such classes. It makes code logic verification and testing much simpler. – Raheel Khan May 13 '13 at 19:07
  • Thanks. Would you mind giving an example of a problem this might avoid? I've never seen a test for this before and would be interested to know. Please feel free not to answer should prefer :) – Basic May 13 '13 at 19:10
  • @Basic: Please have a look at my [[original question here](http://stackoverflow.com/questions/16524235/verifying-code-against-template-patterns-using-reflection)] for more context and usage. See Daniel Hilgarth's answer and the discussion below. As for what problems it may help avoid, this was an after-the-fact measure rather than a forward-looking strategy. – Raheel Khan May 13 '13 at 21:06
  • @RaheelKhan Thanks for the link, No offense but I can't tell you how happy I am I'm not working on that project. Restrictions like that would send me postal within a few months. Good luck on the rewrite in 2 years time. I hope by then you've hired/trained your devs so they can handle details like this themselves. – Basic May 13 '13 at 21:39

2 Answers2

2

This should do the trick

//get the two types in question
var typeB = b.getType()
var typeA = typeB.BaseType;
var interfaces = typeA.GetInterfaces();

//if the length are different B implements one or more interfaces that A does not
if(typeB.GetInterfaces().length != interfaces.length){
   return false;
} 

//If the list is non-empty at least one implemented interface satisfy the conditions
return (from inter in interfaces
        //should be generic
        where inter.IsGeneric
        let typedef = inter.GetGenericTypeDefinition()
        //The generic type of the interface should be a specific generic type
        where typedef == typeof(IKnownInterface<>) &&
        //Check whether or not the type A is one of the type arguments
              inter.GetGenericTypeArguments.Contains(typeA)).Any()
Rune FS
  • 21,497
  • 7
  • 62
  • 96
  • Thank you. I'm wondering why your code does not need to include the `typeof(IKnownInterface<>).MakeGenericType(o.GetType())` method as in @NechytailoOleh's answer. – Raheel Khan May 13 '13 at 18:04
  • @RaheelKhan It kind of does. ´let typedef = inter.GetGenericTypeDefinition()` and the following line does the same – Rune FS May 13 '13 at 18:07
  • Ah I see. I prefer NechytailoOleh's compact comparison but got both points answered here. Thanks again. – Raheel Khan May 13 '13 at 18:15
  • @RaheelKhan the compact version only works with one generic type argument. I was under the assumption that it should work with multiple type arguments where one of them should be A – Rune FS May 13 '13 at 18:23
  • I know and agree. My preference was based solely on the 'Yuckiness' that Query Syntax has for me (even though it is recommended over Method Syntax). Nothing to do with function, just the form. :P – Raheel Khan May 13 '13 at 18:42
1

try:

 o.GetType().GetInterfaces()[0] == 
                   typeof(IKnownInterface<>).MakeGenericType(o.GetType())

http://msdn.microsoft.com/en-us/library/system.type.makegenerictype.aspx

Oleh Nechytailo
  • 2,155
  • 17
  • 26