473,382 Members | 1,423 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,382 software developers and data experts.

Equivalent to run-time dynamic linking in .NET

I have an unmanaged Win32 app that looks up the name of a DLL (unknown at
compile time) from an external location, loads it with LoadLibrary, and then
uses GetProcAddress on three exported functions (whose names and signatures
are known at compile time). The app then calls these functions as needed
throughout its execution. Depending on circumstances, there may be zero, one,
or many separate DLLs loaded that all conform to this pattern (that is, they
all export the same three functions).

I need to convert this app to managed code. It needs to perform the same
behavior: look up a DLL assembly (unknown at compile time) from an external
location, load it somehow and call its "exported" functions (presumably in
..NET these would be public methods of a public class).

Before I dive into the wonderful mess that constitutes System::Reflection,
so that I can supposedly drag the types and methods straight out of the DLLs
themselves, I have 3 questions:

1. Is using System::Reflection the preferred way of doing "run-time dynamic
linking" in .NET?
2. If not, what is the preferred way of handling this type of situation?
3. Does anyone know of any design pattern or at least a well-documented
example for this type of work?

Sean
May 23 '06 #1
11 2040
"Sean M. DonCarlos" <se********@newsgroups.nospam> wrote in message
news:1C**********************************@microsof t.com...
I have an unmanaged Win32 app that looks up the name of a DLL (unknown at
compile time) from an external location, loads it with LoadLibrary, and
then
uses GetProcAddress on three exported functions (whose names and
signatures
are known at compile time). The app then calls these functions as needed
throughout its execution. Depending on circumstances, there may be zero,
one,
or many separate DLLs loaded that all conform to this pattern (that is,
they
all export the same three functions).

I need to convert this app to managed code. It needs to perform the same
behavior: look up a DLL assembly (unknown at compile time) from an
external
location, load it somehow and call its "exported" functions (presumably in
.NET these would be public methods of a public class).

Before I dive into the wonderful mess that constitutes System::Reflection,
so that I can supposedly drag the types and methods straight out of the
DLLs
themselves, I have 3 questions:

1. Is using System::Reflection the preferred way of doing "run-time
dynamic
linking" in .NET?
I hate to use terms like "preferred way". It is the way I do it.
2. If not, what is the preferred way of handling this type of situation?
FWIW: it's my choice.
Does anyone know of any design pattern or at least a well-documented
example for this type of work?


In an application of mine I do pretty much what you suggest to support .Net
"plugins".

In my case there is a base class that has the required method(s). I require
that the plugins be derived fom my base class. I use
Reflection::Assembly::LoadFrom() so that I can load the assembly from where
ever the lookup takes me. The assembly's GetTypes() method returns an array
of types in the assembly. It use the Type class's BaseType member to insure
that I have the kind of class hat I need. I used the GetMethod() member of
the Type class to perform a similar function to GetProcAddress(). Finally
the Invoke member of the MethodInfo class gets me the dynamic invocation
that I need.

Regards,
Will
May 23 '06 #2
Sean M. DonCarlos wrote:
1. Is using System::Reflection the preferred way of doing "run-time dynamic
linking" in .NET?


Here's an example of loading a plugin from an application (using
C++/CLI, assuming you're using VC++ 2005):

#using "Interface.dll"
using namespace System;

Reflection::Assembly^ assembly =
Reflection::Assembly::LoadFrom("Plugin1.dll");
Type^ t = assembly->GetType("Plugin.Plugin1");
Plugin::Interface^ plugin =
safe_cast<Plugin::Interface^>(Activator::CreateIns tance(t));
String^ result = plugin->GetName();
The interface is published from the interface.dll assembly, declared as

namespace Plugin
{
public interface class Interface
{
public:
virtual String^ GetName() abstract;
};
}
And the plugin is implemented like this in Plugin1.dll:

#using "Interface.dll"

namespace Plugin
{
public ref class Plugin1 : public Interface
{
public:
virtual String^ GetName() { return "Hello"; }
};
}
The key is to ensure that each plugin DLL uses the same Interface as the
application. In .NET, just naming two classes the same way alone doesn't
ensure that the two classes are the exact same type. This plugin sample
only works if Interface is the exact same class in both the application
and the plugin. The most common way to ensure this is by referencing the
same Interface (for example, with the #using directive), instead of
#including the declaration for Interface. If you were to use #include
instead of #using, the two Interface classes would be completely
independent, and the application would fail to load the plugin.

In this example I chose to introduce a separate interface.dll, which is
referenced by both the application and the plugin. I believe you could
publish the Interface class from the application itself and reference it
from the plugin, but I haven't tried that. I'm not sure if #using is
allowed for an ".exe" or for a ".dll" only.

Tom
May 23 '06 #3
"William DePalo [MVP VC++]" wrote:
I hate to use terms like "preferred way". It is the way I do it.
I don't much care for the term myself, but I've yet to come up with a better
term that isn't a whole sentence. I was just trying to make sure that before
I invested time and effort learning about reflection that reflection was at
least a valid way of handling the problem, if not the "best" way.
2. If not, what is the preferred way of handling this type of situation?


FWIW: it's my choice.
Does anyone know of any design pattern or at least a well-documented
example for this type of work?


In an application of mine I do pretty much what you suggest to support .Net
"plugins".

In my case there is a base class that has the required method(s). I require
that the plugins be derived fom my base class. I use
Reflection::Assembly::LoadFrom() so that I can load the assembly from where
ever the lookup takes me. The assembly's GetTypes() method returns an array
of types in the assembly. It use the Type class's BaseType member to insure
that I have the kind of class hat I need. I used the GetMethod() member of
the Type class to perform a similar function to GetProcAddress(). Finally
the Invoke member of the MethodInfo class gets me the dynamic invocation
that I need.


If only this paragraph had been in the Visual Studio documentation, it would
have saved a lot of time! Thanks!

Sean
May 23 '06 #4
"Sean M. DonCarlos" <se********@newsgroups.nospam> wrote in message
news:C5**********************************@microsof t.com...
"William DePalo [MVP VC++]" wrote:
I hate to use terms like "preferred way". It is the way I do it.


I don't much care for the term myself, but I've yet to come up with a
better
term that isn't a whole sentence. I was just trying to make sure that
before
I invested time and effort learning about reflection that reflection was
at
least a valid way of handling the problem, if not the "best" way.
> 2. If not, what is the preferred way of handling this type of
> situation?


FWIW: it's my choice.
> Does anyone know of any design pattern or at least a well-documented
> example for this type of work?


In an application of mine I do pretty much what you suggest to support
.Net
"plugins".

In my case there is a base class that has the required method(s). I
require
that the plugins be derived fom my base class. I use
Reflection::Assembly::LoadFrom() so that I can load the assembly from
where
ever the lookup takes me. The assembly's GetTypes() method returns an
array
of types in the assembly. It use the Type class's BaseType member to
insure
that I have the kind of class hat I need. I used the GetMethod() member
of
the Type class to perform a similar function to GetProcAddress(). Finally
the Invoke member of the MethodInfo class gets me the dynamic invocation
that I need.


If only this paragraph had been in the Visual Studio documentation, it
would
have saved a lot of time! Thanks!


A couple things:

1. Don't use Assembly.GetTypes. Use Assembly.GetExportedTypes instead.
That way you don't waste time iterating through all the internal types (that
you won't be able to access anyway) and instead look only at public types.

2. Instead of defining a base class, define an interface - it's lighter
weight, and generally you don't need to impose an implementation base class,
but just a calling contract (i.e. an interface).

3. Put your plugin interface(s) into a separate assembly and strong-name
that assembly. That way your code and the plug-ins are strongly de-coupled
from one another - either can be recompiled independently without causing
the other to become obsolete. If you need to change the interface, then you
change the version number of the interface assembly which results in a
change to the strong name so there's no undetected interface
incompatibilities.

FWIW, the technique you're using for native code also works for managed, at
least if the managed code is written in C++. You can still have a
__declspec(dllexport) function in managed code - the compiler will emit an
unmanaged "thunk" that transitions to managed code and calls the actual
managed function. That "thunk" can be called from any Win32 application -
even one that's not (yet) hosting the CLR.

-cd
May 23 '06 #5
"Tamas Demjen" wrote:
In this example I chose to introduce a separate interface.dll, which is
referenced by both the application and the plugin. I believe you could
publish the Interface class from the application itself and reference it
from the plugin, but I haven't tried that. I'm not sure if #using is
allowed for an ".exe" or for a ".dll" only.


I think I read somewhere that #using "Something.exe" is allowed only if
Something.exe was compiled with /clr:pure or /clr:safe.

Thanks for the example code. Between your suggestions and Will's, I now at
least know that what I was thinking of is possible.

Sean
May 24 '06 #6
"Carl Daniel [VC++ MVP]" wrote:
A couple things:

1. Don't use Assembly.GetTypes. Use Assembly.GetExportedTypes instead.
That way you don't waste time iterating through all the internal types (that
you won't be able to access anyway) and instead look only at public types.
Sounds sensible enough.
2. Instead of defining a base class, define an interface - it's lighter
weight, and generally you don't need to impose an implementation base class,
but just a calling contract (i.e. an interface).
No, I don't need a base class for this. The existing unmanaged app only
cares about the function names and signatures. After that, the DLL providing
the functions can do whatever it wants within reason. An interface will be
fine.

But say I define an interface, and I already know the names and signatures
of the three methods I need implemented, and I already know or can look up
from an external resource the name of the class that will be implementing the
interface, must I get all the exported types? Can't I just use GetType with
the known class name, create an instance of that type, safe_cast to the
interface type, and then call the needed methods, as in Tom's sample?
(Obviously I would put some exception handling in there.)
3. Put your plugin interface(s) into a separate assembly and strong-name
that assembly. That way your code and the plug-ins are strongly de-coupled
from one another - either can be recompiled independently without causing
the other to become obsolete. If you need to change the interface, then you
change the version number of the interface assembly which results in a
change to the strong name so there's no undetected interface
incompatibilities.
Certainly.
FWIW, the technique you're using for native code also works for managed, at
least if the managed code is written in C++. You can still have a
__declspec(dllexport) function in managed code - the compiler will emit an
unmanaged "thunk" that transitions to managed code and calls the actual
managed function. That "thunk" can be called from any Win32 application -
even one that's not (yet) hosting the CLR.


I was unaware that any of the __declspec specifiers worked in managed code.
Shows what I get for spending two years stubbornly refusing to use the
Managed Extensions and then trying to dive right in to C++/CLI.

Thanks for your help!
Sean
May 24 '06 #7
"Sean M. DonCarlos" <se********@newsgroups.nospam> wrote in message
news:C5**********************************@microsof t.com...
I don't much care for the term myself, but I've yet to come up with a
better
term that isn't a whole sentence. I was just trying to make sure that
before
I invested time and effort learning about reflection that reflection was
at
least a valid way of handling the problem, if not the "best" way.
I wasn't a criticism. :-) I've been hanging around here long enough that I
can tell when what I'm about to post is off the beaten path enough to think
about it.

See my reply to Carl.
If only this paragraph had been in the Visual Studio documentation, it
would
have saved a lot of time! Thanks!


You are welcome.

IME, reflection in any language is not something that most developers ever
need to do so you don't find a lot of examples.

If my experience is any predictor, the next issue you may have to deal with
is whether you host the common language runtime explicitly or let it happen
automatically by virtue of building a mixed-mode application.

Regards,
Will
May 24 '06 #8
"Carl Daniel [VC++ MVP]" <cp*****************************@mvps.org.nospam >
wrote in message news:eD**************@TK2MSFTNGP03.phx.gbl...
1. Don't use Assembly.GetTypes. Use Assembly.GetExportedTypes instead.
That way you don't waste time iterating through all the internal types
(that you won't be able to access anyway) and instead look only at public
types.
Thanks. I didn't know that method existed.
2. Instead of defining a base class, define an interface - it's lighter
weight, and generally you don't need to impose an implementation base
class, but just a calling contract (i.e. an interface).
That's true but In my case, not only does the server need to communicate
with its plugins but the plugins need to communicate with the server as
well. For me, it made sense to put that stuff in the base class so that the
plugins could get it "for free".
3. Put your plugin interface(s) into a separate assembly and strong-name
that assembly. That way your code and the plug-ins are strongly
de-coupled from one another - either can be recompiled independently
without causing the other to become obsolete. If you need to change the
interface, then you change the version number of the interface assembly
which results in a change to the strong name so there's no undetected
interface incompatibilities.


We are in complete agreement here. I load the CLR, create an app-domain and
then load the strong-named assembly that contains my base class into it. And
just because I'm a control freak I used the stuff I found here:

http://blogs.msdn.com/junfeng/articles/229648.aspx

to forcibly shove my assembly into the GAC.

Regards,
Will
May 24 '06 #9
Sean M. DonCarlos wrote:
I think I read somewhere that #using "Something.exe" is allowed only if
Something.exe was compiled with /clr:pure or /clr:safe.


Carl's reply confirmed that it's a good idea to separate the interface
DLL from the application and the plugin. This separation also makes it
possible to reuse my plugins with other applications. After all, I'd say
forget about #using "App.exe" -- my original design was fine.

Tom
May 24 '06 #10
Sean M. DonCarlos wrote:
"Carl Daniel [VC++ MVP]" wrote:
A couple things:

1. Don't use Assembly.GetTypes. Use Assembly.GetExportedTypes
instead. That way you don't waste time iterating through all the
internal types (that you won't be able to access anyway) and instead
look only at public types.


Sounds sensible enough.
2. Instead of defining a base class, define an interface - it's
lighter weight, and generally you don't need to impose an
implementation base class, but just a calling contract (i.e. an
interface).


No, I don't need a base class for this. The existing unmanaged app
only cares about the function names and signatures. After that, the
DLL providing the functions can do whatever it wants within reason.
An interface will be fine.

But say I define an interface, and I already know the names and
signatures of the three methods I need implemented, and I already
know or can look up from an external resource the name of the class
that will be implementing the interface, must I get all the exported
types? Can't I just use GetType with the known class name, create an
instance of that type, safe_cast to the interface type, and then call
the needed methods, as in Tom's sample? (Obviously I would put some
exception handling in there.)


Yep. If you already know the full class name you can dispense with the trip
through Get{External}Types().

-cd
May 24 '06 #11
William DePalo [MVP VC++] wrote:
"Carl Daniel [VC++ MVP]"
<cp*****************************@mvps.org.nospam > wrote in message
news:eD**************@TK2MSFTNGP03.phx.gbl...
1. Don't use Assembly.GetTypes. Use Assembly.GetExportedTypes
instead. That way you don't waste time iterating through all the
internal types (that you won't be able to access anyway) and instead
look only at public types.
Thanks. I didn't know that method existed.


I didn't either until ~1 month ago - I was doing exactly what you described.
I'm not sure if that function is new in 2.0, but I don't think so.
2. Instead of defining a base class, define an interface - it's
lighter weight, and generally you don't need to impose an
implementation base class, but just a calling contract (i.e. an
interface).


That's true but In my case, not only does the server need to
communicate with its plugins but the plugins need to communicate with
the server as well. For me, it made sense to put that stuff in the
base class so that the plugins could get it "for free".


Still, if your base class has an implementation error in it, you end up
recompiling both your server and all of the plugins (which may not be a
problem for your app, but it would be for some). I'd define two interfaces:
one that the plugin implements and one that the server implements. Pass the
server interface to an "Initialize" method on the plug-in interface. With
those in place, I'd publish the source code to the base class - it's just a
sample at that point.
3. Put your plugin interface(s) into a separate assembly and
strong-name that assembly. That way your code and the plug-ins are
strongly de-coupled from one another - either can be recompiled
independently without causing the other to become obsolete. If you
need to change the interface, then you change the version number of
the interface assembly which results in a change to the strong name
so there's no undetected interface incompatibilities.


We are in complete agreement here. I load the CLR, create an
app-domain and then load the strong-named assembly that contains my
base class into it. And just because I'm a control freak I used the
stuff I found here:
http://blogs.msdn.com/junfeng/articles/229648.aspx

to forcibly shove my assembly into the GAC.


Excellent!

-cd
May 24 '06 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Bruce | last post by:
I have an application where I would like to be able to allow the user to specify the date format used throughout the program (for internationalization). Then, on a date entry field, I can...
3
by: Prakash | last post by:
hi: I am writting a stored procedure to purge one of our transaction tables. I would like to run this SP periodically, say everyday at 4 am. I am wondering how can I achieve this without...
6
by: exquisitus | last post by:
Hi all, I'm porting a DOS application to run on Linux. I need to replace this function or use an equivalent. Anyone knows how or where I can get this function's equivalent (or maybe someones...
4
by: Jim H | last post by:
Does .NET have an equivalent to java's JMS messaging. I'm not a java programmer but as I understand it a java application can be setup to pass entire objects between processes. Is there some sort...
4
by: steve | last post by:
what's the equivalent to sendmessage? i want to explicitly kill the focus of a control. tia, steve
4
by: Scott Johnson | last post by:
Hi I am converting some code from C# to VB.NET and I have come across a command that I can't find the VB equivalent. The C# command is 'lock' and I think it is used to lock a data type from...
0
by: Rob Blackmore | last post by:
Hi, A simple question I'm sure, but can someone point me in the right direction of how to have the equivalent of 2 projects in VB.Net, 1 that is a standard EXE and 1 that is an ActiveX.EXE that...
2
by: ramu | last post by:
Hi I have to call a vc++ function in a c program. suppose i have a function dword fun(dword arg1, bstr arg2); in vc++. I have to call this function in c. But I don't have dword datatype in...
4
by: pcnerd | last post by:
I've been playing with "classic" VB since version 3. I have VB6 Learning Edition. Recently, I wanted to try VB.NET. I got a beginner's book with a CD with the software & installed it. There are...
11
by: gnuist006 | last post by:
Is there a Delphi equivalent in the C world or Scheme/LISP world ? Recently, Delphi is in resurgence. In Russia people are using like crazy. For example, Bolega has written a free image...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.