consuming a class defined in another assembly
-
i have an app that defines an abstract base class. i have a dll that has a class which inherits from the base class. the app and the dll reside on the same machine. i want to be able to consume the derived class in the dll from my app by class name. so, my app has function that takes an assembly name and class name. i create the derived class and cast it to the base class. how would i do this?
-
i have an app that defines an abstract base class. i have a dll that has a class which inherits from the base class. the app and the dll reside on the same machine. i want to be able to consume the derived class in the dll from my app by class name. so, my app has function that takes an assembly name and class name. i create the derived class and cast it to the base class. how would i do this?
See
Type.GetType
andActivator.CreateInstance
for one way. There are many ways to do this. Lets say you have something like this:App.exe:
public abstract BaseClass {...}
Lib.dll
public MyClass1 : BaseClass {...}In App.exe, you can do something like this:
Type t = Type.GetType("MyClass1, lib.dll");
BaseClass bc = (BaseClass)Activator.CreateInstance(t);If the first statement can't find the assembly (i.e., it's not in the same directory, in the GAC, or configured with a private path or binding path in your App.exe.config file), a
TypeLoadException
is thrown. If the instance can't be created, a number of exceptions might be thrown depending on what the problem is (see the documentation for theActivator.CreateInstance
overloaded method in the .NET Framework SDK for more information). The only problem is that VS.NET won't let you reference a .exe assembly so you will have to compile this on the command line, which isn't hard. SinceMyClass1
derives fromBaseClass
, which is in a .exe assembly, you can't reference it. The compiler doesn't care, it's just that VS.NET won't let you. :( Further, you might consider using a configuration file (.config) so that you can change the types or have a plug-in type system. There are many articles here on CP that cover this, and discuss other ways to load and instantiate a Type by name. Try this search: http://www.codeproject.com/info/search.asp?cats=3&cats=5&searchkw=plugins[^].-----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----
-
See
Type.GetType
andActivator.CreateInstance
for one way. There are many ways to do this. Lets say you have something like this:App.exe:
public abstract BaseClass {...}
Lib.dll
public MyClass1 : BaseClass {...}In App.exe, you can do something like this:
Type t = Type.GetType("MyClass1, lib.dll");
BaseClass bc = (BaseClass)Activator.CreateInstance(t);If the first statement can't find the assembly (i.e., it's not in the same directory, in the GAC, or configured with a private path or binding path in your App.exe.config file), a
TypeLoadException
is thrown. If the instance can't be created, a number of exceptions might be thrown depending on what the problem is (see the documentation for theActivator.CreateInstance
overloaded method in the .NET Framework SDK for more information). The only problem is that VS.NET won't let you reference a .exe assembly so you will have to compile this on the command line, which isn't hard. SinceMyClass1
derives fromBaseClass
, which is in a .exe assembly, you can't reference it. The compiler doesn't care, it's just that VS.NET won't let you. :( Further, you might consider using a configuration file (.config) so that you can change the types or have a plug-in type system. There are many articles here on CP that cover this, and discuss other ways to load and instantiate a Type by name. Try this search: http://www.codeproject.com/info/search.asp?cats=3&cats=5&searchkw=plugins[^].-----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----
Thanks for the reply, however, that didn't work. The call to
Type t = Type.GetType("MyClass1, lib.dll");
t is null. I had to do this,Assembly componentAsssembly = Assembly.LoadFrom( "lib.dll" ); Type t = componentAsssembly.GetType( "MyClass1" );
. Then, the call toBaseClass bc = (BaseClass)Activator.CreateInstance(t);
throws a ClassCastException saying the specified cast is not allowed. Any ideas? BTW, how do you get your code samples in those nice yellow boxes?? -
Thanks for the reply, however, that didn't work. The call to
Type t = Type.GetType("MyClass1, lib.dll");
t is null. I had to do this,Assembly componentAsssembly = Assembly.LoadFrom( "lib.dll" ); Type t = componentAsssembly.GetType( "MyClass1" );
. Then, the call toBaseClass bc = (BaseClass)Activator.CreateInstance(t);
throws a ClassCastException saying the specified cast is not allowed. Any ideas? BTW, how do you get your code samples in those nice yellow boxes??Trust me,
Type.GetType
works so long as the assembly can be resolved. The last bit is important. I've been doing this since 1.0 betas and it is used heavily in our application. Fusion - the assembly binder for the CLR - loads the assembly for a Type if it isn't loaded already because the assembly name is part of the Type. See How the Runtime Locations Assemblies[^] for more information. As far as the "yellow" sections, just put your code between<pre></pre>
tags.-----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----
-
Thanks for the reply, however, that didn't work. The call to
Type t = Type.GetType("MyClass1, lib.dll");
t is null. I had to do this,Assembly componentAsssembly = Assembly.LoadFrom( "lib.dll" ); Type t = componentAsssembly.GetType( "MyClass1" );
. Then, the call toBaseClass bc = (BaseClass)Activator.CreateInstance(t);
throws a ClassCastException saying the specified cast is not allowed. Any ideas? BTW, how do you get your code samples in those nice yellow boxes??godzooky wrote: Thanks for the reply, however, that didn't work. The call to Type t = Type.GetType("MyClass1, lib.dll"); t is null. This is because you need to include the namespace within your string value; it is required to resolve the specified class. The following should work:
Type t = Type.GetType("YourNamespace.YourClass, AssemblyName.dll");
if(t != null)
{
// Your code here.
}- Nick Parker
My Blog -
godzooky wrote: Thanks for the reply, however, that didn't work. The call to Type t = Type.GetType("MyClass1, lib.dll"); t is null. This is because you need to include the namespace within your string value; it is required to resolve the specified class. The following should work:
Type t = Type.GetType("YourNamespace.YourClass, AssemblyName.dll");
if(t != null)
{
// Your code here.
}- Nick Parker
My BlogI appreciate all this info. However, I still can't get it to work. Is there a setting somewhere that needs to be set to a non-default value? I have test projects that do just the above and do not work. The app and the dll are in the same directory. I can't get Type.GetType() to work correctly, but I can get Assembly.GetType() to work. And, CreateInstance() always throws an invalid cast exception. I must be missing something obvious.