|
See Type.GetType and Activator.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 the Activator.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. Since MyClass1 derives from BaseClass , 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" );<br />
Type t = componentAsssembly.GetType( "MyClass1" ); . Then, the call to BaseClass 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-----
|
|
|
|
|
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)
{
}
- Nick Parker My Blog
|
|
|
|
|
I 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.
|
|
|
|
|
I have a question. I have created a C# exe project and installed it as a windows service. In the code at runtime I would like to find the path to the service's executable. Does anyone know a property or method that would do this? Your help is greatly appreciated!
Todd
|
|
|
|
|
This will get the path to the currently running executable:
System.Reflection.Assembly.GetAssembly(this.GetType()).Location;
-Tosi
|
|
|
|
|
Thanks alot David, I appreciated it!
Todd
|
|
|
|
|
I want to give design-time support to a property which is a type of custom class. I guess I have to use some design-time attributes, but I couldn't find the correct one. Below is a sample coding.
public class MyClass
{
public int MyInt {...}
public string MyString {...}
}
public class MyComponent : System.ComponentModel.Component
{
public MyClass MyClassProperty
{
get {...}
set {...}
}
}
I'll really appreciate it if someone can help me with this.
Thanks.
UB
You may stop this individual, but you can't stop us all... after all, we're all alike. +++Mentor+++
|
|
|
|
|
What do you want to happen? Like a Size is for a Control.Size property? You should first make MyClass a struct (you're using this more as a seldomly-used value type that is allocated on the stack). You should also add the CatagoryAttribute and DescriptionAttribute . If you want it expandable like the Size property of a Control , you'll need to implement a TypeConverter and use the TypeConverterAttribute . Optionally, use the ImmutableAttribute , although you can emulate the behavior in your derived TypeConverter . All this is documented in the System.ComponentModel namespace, as well as Design-time Attributes for Components[^] and Enhancing Design-time Support[^], both good sections in the .NET Framework SDK.
-----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-----
|
|
|
|
|
Thank you very much for your help. I thought there's an easier way to do this without using a TypeConverter . I'll look in those sections in the .NET Framework SDK. Thanks for your time
UB
You may stop this individual, but you can't stop us all... after all, we're all alike. +++Mentor+++
|
|
|
|
|
If you create a C# .NET control, will it work with all its functionalities in a Windows 2000 environment or any other environment without the .NET runtime library installed on the system? Is there a way to make it work by adding lines of code?
|
|
|
|
|
If you write something to be used on the .Net runtime, then the .Net runtime must be installed for it to use. Is that a tautology?
Maybe you are asking the wrong question. Why would you want to have a .Net binary run without the .Net runtime environment?
|
|
|
|
|
Well the thing is, I want to build a control that is going to be used in ActiveX containers... I was hoping I could build one using C# instead of writing an ActiveX control... Any thoughts about that particular problem?
|
|
|
|
|
ActiveX is a technology, not a language. You can write one in C++, C#, VB, VB.NET, and many more that are COM compatible. If you write this in .NET, it will require the .NET runtime to be installed, just like Java requires the JRE, C/C++ requires the C/C++ runtime, VB the VB Virtual Machine, etc.
If you don't want to have to install the .NET Framework, then write it in C/C++ and VB, but make sure you include their runtimes (albeit much smaller).
-----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-----
|
|
|
|
|
Tom Larsen wrote:
Is that a tautology?
Good word Tom!
- Nick Parker My Blog
|
|
|
|
|
Hi there,
I'm a newbie in C# and comming from C++/MFC.
I'm building my first application in C#.
I have created a class derived from Object
public class Block : Object
{
Block()
{ Initialize(); }
public bool Initialize()
{ Debug.WriteLine("Block.Initialize"); ... }
...
}
As the array is a 2D array of Block, I have instanciated the arry like that:
Block[,] board=new Block[m_nHeight, m_nWidth];
while default values for m_nHeight is 20 and m_nWidth is 10.
When I look at the trace, I see only 0 calls for the method Block.Initialize.
How can it be possible? Are all the Block object created when I do "m_board=new Block[m_nHeight, m_nWidth];"??? or must I browse the array and call m_board[i, j]=new Block()? If all blocks are created, I should get 200 lines of "Block.Initialize"...
Can anybody explain what's wrong?
Best regards.
Thanks.
|
|
|
|
|
First of all, you don't need to derive from Object . If you don't specify a base class, Object is assumed. This just looks bad.
Second, you're not creating a new instance of Block , only a new Block[] array (which is of type Array ). You won't create a new instance of Block until you use new :
Block[,] board = new Block[m_nHeight, m_nWidth];
board[0, 0] = new Block(); Find more information about arrays at http://msdn.microsoft.com/library/en-us/csref/html/vclrfArraysPG.asp[^].
-----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-----
|
|
|
|
|
Hi,
Thanks for the answer.
So, if I undertand well, in C#, I need to browse my array and instanciate a "new Block" for each cells of the array right?
|
|
|
|
|
Yes, only it's "iterate" not "browse".
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
so, I do a the following:
<br />
...<br />
m_nHeight=20;<br />
m_nWidth=10;<br />
...<br />
m_board=new Block[m_nHeight, m_nWidth];<br />
for (int i=0; i < m_nHeight; i ++ )<br />
for (int j=0; j < m_nWidth; j ++ )<br />
m_board[i, j]=new Block();<br />
but a strange thing, I have inserted a trace inside the constructor of the Block class, and when I look at the trace, instead of having 200 calls of Block.Block, I have 400 calls 20x10=200...
|
|
|
|
|
You had a trace in your Initialize method before. Are you sure you're not getting 200 lines with "Block.Block" and 200 lines with "Block.Initialize"? If not, I'd really need to see the rest of the Block class code and the full creation block in which you gave a fragment of above.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Hi Heath,
I have rebuild the code, and indeed, there are 200 calls now
Thanks
|
|
|
|
|
Hi!
I use RemotingConfiguration.RegisterWellKnownClientType(typeof(type),url) to register a type as a wellknown client type. Is it possible to unregister this type to register it again with another url (or to change the url for the registered type) without restarting my application?
|
|
|
|
|
First, let me advocate that a well-known client Type can't be well-known if you change its URI.
That being said, you can use RemotingServices.Disconnect . If you have a reference to the registered object, just pass it to the static Disconnect method. If you don't have an instance of it available, you can get one using other methods of the RemotingServices class.
Registering it with another URI is as simple as what you've already done.
Another way is to simply shut down the .NET Remoting host, such as a Windows Service, IIS, or some other program, but that's most likely not what you want in this case.
-----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-----
|
|
|
|