|
I develop an application that uses a plugin interface, that the hosting application as well as the plugins implement. Each plugin is loaded via:
newPlugin.Instance = (IPlugin)Activator.CreateInstance(pluginAssembly.G etType(pluginType.ToString()));
(mainly an implementation of http://www.codeproject.com/csharp/PluginsInCSharp.asp
All Plugins are inside a sub directory called "plugins" of the main application.
Now I developed one plugin that should implement a network interface, using external dll's from a framework i wrote some time ago. This framework binary serializes objects, compresses them and sends them over the net. There is a central object library of all sendable objects in a seperate dll.
When I receive such an Object in the Plugin, i can deserialize it without any problem and it is showed correctly while debugging as "object" type (resulting from the deserialization). Now, when I try to cast this object to a structure (that is described in the external dll - the object library - which is the same at the sending and receiving side) i get a "Invalid Cast Exception" in the plugin.
By the way, the object and it's type look correctly while debugging and, i can send such objects from this application to the remote one, that also can cast them, using exact the same dll (the object library).
I searched around a lot, but found no real answer...
Maybe the problem is that "Activator.CreateInstance" loads the plugin assembly into a wrong appDomain, because the remote application does not use plugins and refers to the object library - dll directly.
The hosting application as well as the plugin reference the object library dll, and the dll file is present in the main application directory as well as in the plugins subdirectory.
The source code is a bit complex, so i hope that someone might be able to help me just with this description of the problem.
Thx in advance,
Gerd
|
|
|
|
|
Gerd,
You said you tried casting the loaded IPlugin to type to a structure described in the external dll. Is the plugin dll's IPlugin implementation actually a type of the structure you're casting to? I'm a little confused by your post - if you can clarify a bit, maybe show the source code (or the skeleton, e.g. class inheritance) of the external dll's IPlugin implementation, that may help.
|
|
|
|
|
Ok, sorry, the question was not quite clear as I can see now.
Here's the cut-down problem:
There is a Main Program (exe), a Plugin dll, and an object library dll.
The Program loads and instances the Plugin dll, that works fine and is not the question.
But assume that I now have an object passed to the Plugin over the net.
The object is constructed using a class or structure defined in the object library dll on a remote computer.
I now try to cast the object to it's class / struct from within the plugin:
using objectLib;<br />
<br />
public void inputObject (object myObject) <br />
{<br />
objectLib.myClass newClass = (objectLib.myClass)myObject;
}<br />
During debug, myObject.GetType() results in "objectLib+myClass", what should be fine...
When I create a test object locally, say:
<br />
objectLib.myClass testClass = new objectLib.myClass();<br />
then testClass.GetType() also returns "objectLib+myClass", but neither
myObject is objectLib.myClass nor
myObject.GetType() == testClass.GetType()
returns true.
When I use this code only in an exe, without the plugin interface, it works fine.
|
|
|
|
|
Aha, now I understand.
First question is obvious: why is inputObject method taking an object, and not a objectLib.myClass object? My bet is, if you changed the parameter to type objectLib.myClass, the issue will resolve itself through compiler errors leading you to the real problem.
As far as the real problem goes, 2 possibilities come to mind. The first is versioning issues: is the remote process that invokes inputObject built with the exact same version of the object library? Perhaps you could check this by seeing if
myObject.GetType().Assembly == testClass.GetType().Assembly My guess is that the assemblies don't match either, which could indicate different versions of the same assembly; e.g. Main App is using objLib version 2, but the remote process is using objLib version 1.
What I recommend here is making both the main program, the remote process (server?), the plugin dll(s) and the object library all be single projects but under a single solution in Visual Studio, then just reference the projects as needed.
The other thing that comes to mind is AppDomain weirdness. Unfortunately, I'm not experienced with AppDomains enough to give you any meaningful help. The most I can say is, I'm doing something similar to what you're doing (e.g. having a remote process pass a shared object to another process, and it does indeed work).
|
|
|
|
|
I will test the assembly check tomorrow, maybe something will show up there.
The reason for using the object type is, that there are actually several types possible, and the action performed in inputObject depends on the object's type. Why? Because all network communication is performed using (compressed) binary serialized objects...
I tried to copy the objectLib dll from output directory manually and replace all occurrences, but that wasn't successful - so i think that the problem has to do with paths to the plugin etc...
The thing that confuses me a bit is, that although myObject has the correct type (name) - i get the Invalid Cast Exception. So appDomain should be the problem i think...
Maybe someone out there is aware of it...
Gerd
|
|
|
|
|
Ok, finally a figured out what was going on:
Although all used object library dll'd were the same, the hosting application as well as the plugin had a referenced objectLib.dll in the assembly path, say:
bin/debug/objectLib.dll and
bin/debug/plugins/objectLib.dll
Somehow .net used the one in
bin/debug/objectLib.dll to deserialize the object, but for casting, it was using
bin/debug/plugins/objectLib.dll . Using strong names did not resolve the problem either, so i finally referenced the objectLib.dll for the Plugin directly to the one in
bin/debug/objectLib.dll and selected "Copy Local = False".
And suddenly everything was working fine...
Maybe someone will find this solution usefull
Gerd
|
|
|
|
|
Are you using the same dll for both the first creation and the typecast? It sounds like you may have different versions of the same object (if you compile the dll twice, even if the code is identical, you could end up with different object types). I would try to send the object using xml serialization, then put a break point on the receiving end to see that something serialized from that side has the same version and publicKeyToken as the one being received.
|
|
|
|
|
It also looks like newPlugin is a singleton. Could it be that you are sending two types of plugins but then casting to a different type? For example, maybe you have the following...
interface A { }
struct B : A { }
struct C : A { }
newPlugin.Instance = new B();
newPlugin.Instance = new C();
C foo = (C)newPlugin.Instance; // Throws exception if you can only assign Instance property once
B foo = (B)newPlugin.Instance; // Throws exception if the second assignment overwrites the first
Also, it would be helpful to look at the output of ".GetType().FullName" from the immediate window while running, so you know what type you are dealing with.
|
|
|
|
|
thank you, but its not the type of plugin I'm dealing with. Please have a look on my previous answer, I've tried to clearify the problem.
|
|
|
|
|
Hello
I can't find the event lostfocus in txtbox
and i need to correct how the value will be display if the user didn't put it in the correct way and want to leave.
Thanks a lot
Assaf
|
|
|
|
|
The event is called Leave, I believe.
You can change the value in the textbox on the leave event
Christian Graus - Microsoft MVP - C++
"I am working on a project that will convert a FORTRAN code to corresponding C++ code.I am not aware of FORTRAN syntax" ( spotted in the C++/CLI forum )
|
|
|
|
|
Thank you Christian
We called the event is leave and the lostfocus is a property ?
Assaf
|
|
|
|
|
No, the Leave event ( if I've got it right ) is called when a control loses focus. There is no 'lostfocus' property. The object sent to the event is the control that has lost focus.
Christian Graus - Microsoft MVP - C++
"I am working on a project that will convert a FORTRAN code to corresponding C++ code.I am not aware of FORTRAN syntax" ( spotted in the C++/CLI forum )
|
|
|
|
|
|
I suggest using the Validating event instead of Leave. This adds the possibility to cancel the action if the value can not be formatted correctly.
-^-^-^-^-^-
no risk no funk ................... please vote ------>
|
|
|
|
|
I would like to pass a collection of classes as part of the parameters for the constructor of a class.
It was suggested to use an arraylist.
How does it fit within my code?
public class Table
{
public Table (Database _database, string _tableName)
{
}
}
public class Column
{
public Column ( ref Database _database,
ref Table _table,
ref string _dataType,
ref string _columnName,
bool _primaryKey,
string _fkReferences)
{
}
public Column ( ref Database _database,
ref Table _table,
ref string _dataType,
ref string _columnName,
ref bool _primaryKey)
{
}
public bool PrimaryKey
{
get
{
return PrimaryKey;
}
set
{
PrimaryKey = value;
}
}
public string fkReference
{
get
{
return fkReference;
}
set
{
fkReference = value;
}
}
}
Jon
|
|
|
|
|
If you can't use .NET 2.0, I'd recommend wrapping the arraylist in a typesafe class. either way, it becomes another member variable, which is set by another parameter added to your constructor.
Christian Graus - Microsoft MVP - C++
"I am working on a project that will convert a FORTRAN code to corresponding C++ code.I am not aware of FORTRAN syntax" ( spotted in the C++/CLI forum )
|
|
|
|
|
i'm using .net 2.0, what do you suggest then?
Jon
|
|
|
|
|
i wanna show a transparent form then i wanna draw something on it at run time, how do
|
|
|
|
|
|
I'm working on an application where I need to capture minimize and restore (all of them) and I ran into a problem with my current method...
At the moment I have an override in winproc to look for "size_minimize" and then it'll prompt me. I also look for the system command "SC_RESTORE" to reset it, but I have an issue, if you open the application minimize and then use tasksmanager's "switch to" it doesn't send the "SC_RESTORE" and this will cause a horrible problem! The app will stop working till they minimize and restore it normally...
I HAVE to shutdown my background workers when the app is minimized, and restore them when the user restores the app...
Here is my current winproc
protected override void WndProc(ref System.Windows.Forms.Message m)
{
bool bwincmd = false;
switch (m.Msg)
{
case 0x112:
switch (m.WParam.ToInt32() & 0xFFF0)
{
case 0xF030:
bwincmd = true;
break;
case 0xF010:
setprogramedmove();
bwincmd = true;
break;
case 0xF120:
bMinimized = false;
break;
}
break;
case 0x0005:
switch (m.WParam.ToInt32())
{
case 0x1:
if (this.OnMinimize != null)
{
this.OnMinimize(this, EventArgs.Empty);
}
break;
}
break;
}
if (bwincmd)
{
return;
}
else
{
base.WndProc(ref m);
}
}
I have no idea how taskmanager is restoring the app without sending SC_RESTORE
-Spacix
All your skynet questions[^] belong to solved
|
|
|
|
|
You can set up event handler for form's resize event and check for the window state there.
Also, have a look at http://www.codeproject.com/csharp/windowstatemonitor.asp
I don't know if it solves the problem with task manager but I hope you find it useful
|
|
|
|
|
Ahh crap, it has the same exact issue... Thanks for the input though
The hook methood used is seems like more overhead...
I guess it is easier people who havn't written in Win32 C; IE those who don't handle winproc their self and just want the events to fire.
Even like my application if thie 'bug' occurs and you unfocus the form (goto another window) then click back on the taskbar(or Alt-Tab as both send SC_RESTORE) the state is restored because the command is sent (cool!) but now I need to figure out what command is being sent from taskmanager...
Taskmanager is a weird application! maybe because it loads KM independent from the shell? This looks like a job for Microsoft (I'll get back to everyone in 5 to 6 months )
Just so you know I am capturing the resize event as you said, look at my code I posted the winproc has a case "0x0005" aka WM_SIZE where I trigger my minimize event...
-Spacix
All your skynet questions[^] belong to solved
-- modified at 14:47 Tuesday 4th September, 2007
|
|
|
|
|
You could also use the tool "Spy++" that comes with visual studio .net to watch what messages are passed between windows and your app.
|
|
|
|
|
Yea I did that, which is how I knew it doesn't send SC_RESTORE (other than it doesn't work, but was my reason "why" it didn't work...)
Here is my screen cap from gVIM of the commands:
http://img72.imageshack.us/my.php?image=commandsvimzs0.gif
for some reason imageshack added transparency to my image (so it looks funny on their background...)
|
|
|
|