3

I have custom assembly that is loaded on runtime.

at this point i have code that loads dll and can create new instance of object andexecute method.

How can i verify that the class implements all functions i have defined in interface.

(i am trying to create plug in system with different action that can be switched on runtime, to provide different behaviour).

where my code would be like this is main program:

public Interface IArticleManager{
 void SetMenuId(int MenuId);
 void SetMenu(string name);
 void SetContent(string content);
 bool Save();
}

my class libraries (disconnected you can see it from solution)

public class XmlArticle{
    public void SetMenuId(int MenuId){
       //some implementation
     }
     public void SetMenu(string name){
       //some implementation
}
     public void SetContent(string content){
       //some implementation
}
    public bool Save(){
}
}


public class SqlArticle{
    public void SetMenuId(int MenuId){
       //some implementation
     }
     public void SetMenu(string name){
       //some implementation
}
     public void SetContent(string content){
       //some implementation
}
    public bool Save(){
}
}
cpoDesign
  • 8,953
  • 13
  • 62
  • 106
  • 3
    I just can't figure out. Why do you define an interface, but don't inherit concrete implementations from it? – Daniil Novikov Feb 21 '12 at 13:06
  • Your classes need to implement your interface. That's the purpose of interfaces, so you don't need to check whether or not the classes have all required methods... – Daniel Hilgarth Feb 21 '12 at 13:10
  • @DaniilNovikov: because my interface is living in main program, and the class does not necessary has to have one, but i do want to match it agains my interface that lives in main programm, to ensure compatibility. – cpoDesign Feb 21 '12 at 13:10
  • Duplicate (Sorry I posted wrong link) http://stackoverflow.com/questions/5114469/how-to-check-whether-an-object-has-certain-method-property – Lloyd Feb 21 '12 at 13:12
  • 1
    @Lloyd: Nope. His classes don't implement any interface... – Daniel Hilgarth Feb 21 '12 at 13:13
  • 4
    Move your interface in the separate assembly. Reference this assembly to main programm and where it's required. Inherit this interface in concrete implementations. – Daniil Novikov Feb 21 '12 at 13:14
  • @DaniilNovikov Sorry updated link now, – Lloyd Feb 21 '12 at 13:17
  • From my link posted, you could create your own Extension Method on the Object type and follow the same principal as posted in this answer. http://stackoverflow.com/questions/5114469/how-to-check-whether-an-object-has-certain-method-property – Lloyd Feb 21 '12 at 13:18

4 Answers4

3

Basically, to rephrase, you want to check if a class defines an interface's contract even if it doesn't explicitly implement that interface?

This is extremely non-trivial and a very, very bad idea. Instead, I would strongly recommend you refactor your plugin interface into a contract assembly, and reference the assembly from both your plugins and main application. Then, your plugins can actually implement the contract and you get compiler protection from messing up the implementation.

If you insist on going down this route, however:

var interfaceType = typeof(IArticleManager);
var targetType = typeof(SqlArticle);
foreach(var member in interfaceType.GetMembers())
{
    var targetMember = targetType.GetMember(member.Name);
    // compare the arguments, generic constraints, etc here
}

I'll leave it to you to do the comparison, because its quite honestly a substantial amount of coding. You need to check if the member is a property, event, or method, generic or nongeneric, etc.

David Pfeffer
  • 38,869
  • 30
  • 127
  • 202
  • +1 for the second part of your answer, -1 for showing him a way to do exactly what he asked although this most likely will burn him later. – Daniel Hilgarth Feb 21 '12 at 13:12
  • 3
    @DanielHilgarth There are some legitimate reasons for doing this -- I actually did it once. I was creating a message bus and wanted users to be able to plug their own interface in place of my IConsume interface, so I just required that they provide an interface with the same signature. It isn't pretty, but if you MUST have loose coupling with no compile time reference between the assemblies, this is the only way to do it. – David Pfeffer Feb 21 '12 at 13:16
  • Note that the difference between what I did and what the OP wants to do is that I hard-coded an interface spec, whereas it seems like the OP wants to be able to validate any interface. – David Pfeffer Feb 21 '12 at 13:17
  • @DavidPfeffer: Thank you for your input, it is much apperciated – cpoDesign Feb 22 '12 at 08:37
1

Checking that a class implements all methods in an interface is of no use unless it actually implements the interface itself - the fact that it has the same method names ends up being just coincidence.

To check that an object instance implements an interface you:

if (obj is IArticleManager)

which would return true.

However if you then want to actually use the interface's methods its better (less casting):

IArticleManager manager = obj as IArticleManager;  
if (manager != null)  
{ do stuff }
kaj
  • 5,133
  • 2
  • 21
  • 18
1

It seems like what you need to do is move the interface into a separate assembly, which only contains interfaces which is accessible to both the 'main program' and the dynamically loaded DLLs.

So, in order to create a dynamically loaded DLL and expect it to work within your infrastructure, the author will first need to reference the interface assembly and then implement the provided interface.

Mark Withers
  • 1,462
  • 5
  • 16
  • 34
0

And what is the purpose of IArticleManager when you can not use it anywhere?

That aside, if we accept that you want to make a very loose plugin system, you could mandate that every plugin assembly has exactly one public class and then instantiate that class via reflection, and call out it's methods via reflection while passing appropriate arguments.

As with every plugin or other external code you should validate the output and protect your app from errors (i.e. catch and log the plugin exceptions). This would also handle non valid plugins (ones that don't have the required signature)

clearpath
  • 916
  • 8
  • 24