PHP User Warning: fetch_template() calls should be replaced by the vB_Template class. Template name: bbcode_highlight in ..../includes/functions.php on line 4197

PHP User Warning: fetch_template() calls should be replaced by the vB_Template class. Template name: bbcode_highlight in ..../includes/functions.php on line 4197

PHP User Warning: fetch_template() calls should be replaced by the vB_Template class. Template name: bbcode_highlight in ..../includes/functions.php on line 4197

PHP User Warning: fetch_template() calls should be replaced by the vB_Template class. Template name: bbcode_highlight in ..../includes/functions.php on line 4197
[RESOLVED] Executing a method from the assembly without first referencing it?-VBForums
Results 1 to 13 of 13

Thread: [RESOLVED] Executing a method from the assembly without first referencing it?

  1. #1

    Thread Starter
    PowerPoster cicatrix's Avatar
    Join Date
    Dec 2009
    Location
    Moscow, Russia
    Posts
    3,654

    Resolved [RESOLVED] Executing a method from the assembly without first referencing it?

    I'm returning to my old question since I've never been able to find an answer.
    For example I have a class library A with a method Method, is there a way to load this assembly from my application B and execute this method (A.Method) without putting a reference to assembly A?

    My idea isn't that the idea behind System.Reflection?

    So far, I can only load the assembly, I can even enumerate classes, members, etc, but I cannot figure out how to invoke methods and read property values.

  2. #2
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: Executing a method from the assembly without first referencing it?

    First of all, a method is in a class, not a class library, but I'm sure that's just a typo.

    If you can load the assembly using reflection (Assembly.Load or something I think?), then you can enumerate the Types in that assembly (GetTypes I guess). Once you have the Type you need, you can enumerate the Methods, Properties, Fields, etc, by the GetMethods, GetProperties, GetFields, etc methods. These will return arrays of MethodInfo, PropertyInfo and FieldInfo objects respectively. You can specify a number of BindingFlags in the GetMethods/Properties/Fields as well to determine which members are returned (for example, only public members, only static (shared) members, etc).

    Finally, once you have a MethodInfo object, you can invoke it using its Invoke method. You need to specify an instance of an object to invoke it on (unless it is shared), and a list of parameters. Obviously you have to make sure the list of parameters is valid, in the correct order and the correct types, because the IDE can't check that for you in this case.

    For a PropertyInfo object (and probably also a FieldInfo object though I've never used those) you can get the value of the property using the GetValue method. You pass in the instance of the class you want the value from as the first parameter, and you can usually get away with passing Nothing as the second parameter. You use SetValue to set the value in the same way, except obviously you also need to pass the new value.

    Instead of looping through all members you can also just use GetMethod, GetProperty or GetField (singular) and pass in the name of the member to get just one member.

    So for example:
    vb.net Code:
    1. Dim asm As Assembly = Me.GetAssembly(...)
    2.  
    3. ' Loop through all types
    4. For Each t As Type In asm.GetTypes()
    5.  
    6.    If t.Name = "SomeClassInApplicationA" Then
    7.        
    8.        ' Create an instance (you might have this already)
    9.        Dim instance As Object = Activator.CreateInstance(t)
    10.  
    11.        ' Get a method called MethodA and invoke it
    12.        Dim mi As MethodInfo = t.GetMethod("MethodA")
    13.        mi.Invoke(instance, Nothing) 'no parameters, perhaps you can omit them dunno
    14.  
    15.        ' Get a property "Value" and set its value
    16.        Dim pi As PropertyInfo = t.GetProperty("Value")
    17.        pi.SetValue(instance, 3.1415, Nothing)
    18.  
    19.    End If
    20. Next

    Something like that at least.

  3. #3

    Thread Starter
    PowerPoster cicatrix's Avatar
    Join Date
    Dec 2009
    Location
    Moscow, Russia
    Posts
    3,654

    Re: Executing a method from the assembly without first referencing it?

    Thanks, I must test this and sort some things out but it appears that this is possible, after all.
    The idea behind it is to create a plugin architecture without referencing a base app and a plugin app to some third dll containing a shared interface.

  4. #4
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: Executing a method from the assembly without first referencing it?

    This is how plugins are usually (always?) made. You'd create an interface (or possibly abstract class) IPlugin, which usually has some Initialize or Start method (and possibly a Stop method too). You can supply this plugin to developers, who create classes that implement the plugin. You cannot know at this time what those classes do, because they don't exist yet. But you do now that they implement the IPlugin interface, and so they must have a Start method. So what you can do is find all Types in the assembly that implement IPlugin, create an instance of them (cast to a IPlugin) and then invoke their Start method. In fact you don't need to invoke the method using Reflection at all, you can cast the instance to an IPlugin and simply call its Start method:
    vb.net Code:
    1. For Each t As Type In asm.GetTypes()
    2.    If GetType(IPlugin).IsAssignableFrom(t) Then
    3.       't implements IPlugin
    4.  
    5.       Dim instance = DirectCast(Activator.CreateIntance(t), IPlugin)
    6.       instance.Start()
    7.    End If
    8. Next

  5. #5

    Thread Starter
    PowerPoster cicatrix's Avatar
    Join Date
    Dec 2009
    Location
    Moscow, Russia
    Posts
    3,654

    Re: Executing a method from the assembly without first referencing it?

    No, no, no. I have already tried that.
    The problem lies with the fact that IPlugin that I get from my plugin assembly is not the interface I use in the host application. They may look the same, but they're different to CLR. In order to implement this I must create a third DLL containing the IPlugin interface and have both the host application and the plugin assembly reference to this third DLL. I don't want this to happen since I don't want to distribute an additional DLL.

    Check out this thread: http://www.vbforums.com/showthread.p...ghlight=Plugin

  6. #6
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: Executing a method from the assembly without first referencing it?

    I see. Having a DLL that both yours and the plugins application would reference is certainly a lot easier but if you don't want that...

    But how are you distributing your IPlugin interface then, if not in a DLL?



    Anyway, you could get away with what I posted in my first reply, but you'd not be using any IPlugin interface at all. There's nothing to guarantee that the plugin that someone else wrote contains all the methods you are trying to invoke. Sure, you could check that before invoking the method (otherwise you'd probably get a null reference exception or some other exception on trying to load the method), but it isn't a very good approach.

  7. #7

    Thread Starter
    PowerPoster cicatrix's Avatar
    Join Date
    Dec 2009
    Location
    Moscow, Russia
    Posts
    3,654

    Re: Executing a method from the assembly without first referencing it?

    Well, the whole idea is that I can't use interfaces for what I'm trying to do. So I will have to manually ensure that the plugin has all the methods I need. Right now I'm trying to do what you initially suggested. I'll report the results here )))

  8. #8

    Thread Starter
    PowerPoster cicatrix's Avatar
    Join Date
    Dec 2009
    Location
    Moscow, Russia
    Posts
    3,654

    Re: Executing a method from the assembly without first referencing it?

    I think I made this work finally.
    Here's what you need.

    1. A plugin with some public method, like this:
    Code:
    Public Class Plugin
        Public Function SampleMethod() As String
            Return "Hello, this is a test message from the plugin."
        End Function
    End Class
    2. Then I compile the plugin into a class library called Sample plugin.

    3. Then I create a host application:

    vb Code:
    1. Imports System.Reflection
    2. Imports System.Runtime.Remoting
    3.  
    4. Public Class Form1
    5.     Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    6.  
    7.         Dim pluginpath As String = "D:\VS Projects\PluginApp\SamplePlugin\bin\Debug\SamplePlugin.dll"
    8.  
    9.         ' Loading assembly:
    10.         Dim asmplugin As Assembly = Assembly.LoadFile(pluginpath)
    11.  
    12.         ' Find the Plugin type in it
    13.         Dim t As Type = Aggregate asmtype In asmplugin.GetTypes Where asmtype.Name = "Plugin" Into First()
    14.  
    15.         ' Create an instance of this type using Activator class'
    16.         ' You will need a full name, i.e. <Assemly>.<Type>, in this case "SamplePlugin.Plugin"
    17.         Dim i As ObjectHandle = Activator.CreateInstanceFrom(pluginpath, "SamplePlugin.Plugin")
    18.  
    19.         ' Get the method info from loaded type:
    20.         Dim mi As MethodInfo = t.GetMethod("SampleMethod")
    21.  
    22.         ' Invoke it against the created instance. Note that first you need to unwrap it:
    23.         Dim ret As String = mi.Invoke(i.Unwrap, Nothing).ToString
    24.         MsgBox(ret)
    25.     End Sub
    26. End Class

    Well, what can I say, it works. Thanks NickThissen for nudging me to the right direction. Still no rep for you because the forum engine won't allow it

    Thread resolved.

    Just some additional info. You won't probably need to mess with Activator if you declare your plugin method as Shared. But I didin't test it.

  9. #9
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: [RESOLVED] Executing a method from the assembly without first referencing it?

    But now you are assuming all plugins are called Plugin (actually you are only loading one at most), and that all of those classes contain a method called SampleMethod, and that it returns a String. How can you be sure? Without the Plugin class implementing an interface you can't really be sure unless you check all that.
    You could check if the class contained all the methods you need by just keeping a list of their names and checking them... For example:
    vb.net Code:
    1. Private _PluginMethods As New List(Of String)
    2.  
    3. Public Sub New()
    4.    _PluginMethods.Add("SampleMethod")
    5.    _PluginMethods.Add("AnotherMethod")
    6.    _PluginMethods.Add("Start")
    7. End Sub
    8.  
    9. Private Function IsValidPlugin(ByVal t As Type) As Boolean
    10.    For Each method As String In _PluginMethods
    11.       If t.GetMethod(method) Is Nothing Then Return False
    12.    Next
    13.    Return True
    14. End Function

    This way you could run the IsValidPlugin method against each type you get, and if it returns True at least you know it has all the methods. You still don't know whether the types they return (if any) are correct (I'm not sure if you can check that at all without invoking them, and I wouldn't invoke them just to check it!) or whether the class was intended as a plugin at all. Someone could have a class which just happens to have all the methods with the same name, possibly with a completely different meaning. Not likely if there's loads of methods in your plugin, but plugins often have only a couple of methods...

    Of course you can just 'require' that all plugins are in some destined folder, or something, and if someone puts a non-plugin class in that folder things may go wrong. But I still don't see why a simple DLL isn't an option for you. It solves all these problems by simply providing one interface.


    EDIT
    On an unrelated note, if you have the Type already (t), you can much more easily use Activator.CreateInstance instead of CreateInstanceFrom and then supply the name of the plugin as a string (again). You'd get an Object in return so your code would look like this
    Code:
            ' Create an instance of this type using Activator class:
            Dim i As Object = Activator.CreateInstance(t)
    
            ' Get the method info from loaded type:
            Dim mi As MethodInfo = t.GetMethod("SampleMethod")
    
            ' Invoke it agains the created instance. Note that first you need to unwrap it:
            Dim ret As String = mi.Invoke(i, Nothing).ToString

  10. #10

    Thread Starter
    PowerPoster cicatrix's Avatar
    Join Date
    Dec 2009
    Location
    Moscow, Russia
    Posts
    3,654

    Re: [RESOLVED] Executing a method from the assembly without first referencing it?

    Well, of course I'll do some due checks and tests before using it. This is, after all, a sample code just to illustrate how this works.
    Still, in order to meet some requirements, a plugin MUST implement a method called 'Work' for example.
    An interface implementation is a guarantee that this class contains all necessary members and their types match the agreement. I can check it even without using VS.Net interfaces.

    Quote Originally Posted by NickThissen View Post
    But I still don't see why a simple DLL isn't an option for you. It solves all these problems by simply providing one interface.
    I don't want a third dll. Imagine i supplied an application which references to DLL exposing a plugin interface.
    Then some time later (a year or two, who knows) I will have to make sure I have the same dll referenced in my plugin. It creates dependencies where you don't need any. Besides, two ways of doing thing are always better than one.

  11. #11
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: [RESOLVED] Executing a method from the assembly without first referencing it?

    So let's say for a minute I want to create a plugin for your application. How would that work? Would I contact you and you would give me a list of methods that I have to implement? What if I forget one? My plugin wouldn't work, and if you did your checks right, your application would tell me that only once I try running it. If you didn't do your checks right, it might crash, possibly without me having the faintest idea why. I could go weeks without knowing what I did wrong, until I realize that I spelled 'Initialize' as 'Initialise' by accident...

    What if you decide you want a new method? Or want to name your method differently? You'd have to contact all developers and tell them they have to change their classes manually.

    Wouldn't it be much easier if you just handed me a DLL with a single Interface, so I could implement the interface and be sure that it works?
    If you want to make a change to your plugin, you just distribute a new DLL with the new interface, and I could let Visual Studio do most of the changes for me (name changes for example). I would simply open my class into Visual Studio, and it would tell me that some method is not implemented, or that some existing method implements a method that does not exist in the interface. I hit either 'Implement method' or the Delete key and I'm done.


    It's your own choice of course, but to me it sounds as if you are reinventing interfaces, just so you don't have to distribute one extra DLL.

  12. #12

    Thread Starter
    PowerPoster cicatrix's Avatar
    Join Date
    Dec 2009
    Location
    Moscow, Russia
    Posts
    3,654

    Re: [RESOLVED] Executing a method from the assembly without first referencing it?

    Yes, normally, you ask a developer how to do a plugin or refer the documentation.
    If there is said that a plugin must implement method A and B and if you will forget to implement method B it will be your problem, because my application won't accept your creation as a compatible plugin.
    The nice thing about this approach is that if I decide to implement a new plugin method I will simply add it and it will have no impact on old ones. I will simply say with a new release that to their convenience there is another method called C and if they like they may use it starting from version 2, etc.

    In the situation when I give you a dll with an interface, adding more methods to it will render all previous plugins useless since they don't implement method C.

  13. #13
    Junior Member rkinci's Avatar
    Join Date
    Jan 2012
    Location
    Maine
    Posts
    19

    Re: [RESOLVED] Executing a method from the assembly without first referencing it?

    Executing a method without using interfaces or references does have uses. I want the option to use SqlServerCe (*.sdf) databases in my application. I can use the system.data.common namespace for everything except the inititial creation of a new blank database. I would not reference a dll that I might not use just so I could have the option of creating a new sdf database. Below is the code that I am using to create a new database without an interface or a reference.

    Code:
    Imports System.Reflection
    Public Class CreateSDF
        Public Shared Sub CreateDatabase(ByVal SqlServerCe_FileName As String, ByVal ConnectionString As String)
            Dim assembly As System.Reflection.Assembly = System.Reflection.Assembly.LoadFrom(SqlServerCe_FileName)
            CreateDatabase(assembly, ConnectionString)
        End Sub
        Private Shared Sub CreateDatabase(ByVal SqlServerCe_Assembly As System.Reflection.Assembly, ByVal ConnectionString As String)
            Dim expectedFullname As String = "System.Data.SqlServerCe, Version=3.5.1.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91"
            If SqlServerCe_Assembly.FullName <> expectedFullname Then
                Throw New Exception("The assembly passed in is not the one I want.  I want this one-->  " & expectedFullname)
                Exit Sub
            End If
            Dim ClassNameType As String = "System.Data.SqlServerCe.SqlCeEngine"
            Dim methodname As String = "CreateDatabase"
            Dim typ As Type = Nothing
            typ = SqlServerCe_Assembly.GetType(ClassNameType)
            Dim inst As Object = Activator.CreateInstance(typ, {ConnectionString})
            For Each m As MethodInfo In inst.GetType.GetMethods
                If m.Name = methodname Then
                    m.Invoke(inst, {})
                End If
            Next
        End Sub
    End Class
    This is the best I can do with what I know.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Featured


Click Here to Expand Forum to Full Width