|
I have an application that relies on assembilies. The application has an interface defined and when an assembly is loaded checks to see if the class loaded implements the interface. The problem is that the interface is defined in one folder and the assembly is defined in another folder (the assembly folder is not a sub-folder of the first, however I might make it a sub-folder later on. Would that make a difference??). I am little unsure on how to do this. Implementing the interface is where I get stuck:
dir A:
public interface Drivers{}
public class DriverManager{
//verifies that the assembly loaded implements interface Drivers
}
dir B (contains the Assembly):
public class Driver1 : Drivers (how do i reference the interface here???)
{}
The problem is that I cannot get the class Driver1 to compile because it cannot find the interface Drivers due to the fact that Drivers resides in a different directory.
|
|
|
|
|
It has nothing to do with the directory.
namespaces is the key. If you were going to implement the
IDisposable interface how would you be able to do that if that
were the case?
If it is in a different namespace then add the using MyInterfaceNamespace
or use the full namespace and interface name were you declare the interface.
Bo Hunter
|
|
|
|
|
I did include the the namespace with using. When I include all the files in the same directory. I am able to get it to compile. Is there a path I need to set like in Java?
|
|
|
|
|
I can see how you might not be able to get it to RUN but I'm not sure about the compile part...
Quick checklist for ya!!
1) 3 projects (Interfaces, Implementer of interfaces, User of interfaces)
2) All projects loaded in a single solution
3) Implementer and User have project based references to Interfaces.
The load methods of assembly generally require the path to be specified or that the loaded assembly be "relative" to the callers assembly!
More Info!
|
|
|
|
|
I added the two projects to the same solution and referenced one to the other. I use the Loadform method and pass the entire path of the dll. In fact, the interface is in the same namespace as the class that trys to implement that interface. But the that class is part of an dll that depends on the host application (where the interface resides) and is in a different directory. Even when using Microsoft Intellisense, it is not able to detect that the interface and class are in the same namespace (I do include using statement in class definition). I am not sure if its because the two files are in separate dir or in different projects.
I just gave the Interface and the implementer of the interface different namespaces and I get an error when trying to compile complaining that the other namespace does not exist. Here's the error message:
"The type or namespace name 'IDrivers' could not be found (are you missing a using directive or an assembly reference?)"
I would apprecitate any help provided as I am new to C# and am completely stuck on this. Thanks
|
|
|
|
|
No probs with the helping... we'll get this one cracked!!
If I can try to explain how I think you want to implement what I think your trying to do and you can scream at me and tell me I'm stupid
* You have a forms app
* You have an assembly dll with interface definitions
* You have another assembly with an implementation of said interfaces.
You want to Have your app know about only the interfaces and dynamically at run time look into a dll assembly and instantiate a class which implements the interface...
This is how you do it...
* In a solution add the three projects.
* In your Main app in solution explorer you go to "references" and then right click and select "Add Reference". When the dialog comes up select the "Project References" tab and select the project which defines the interfaces.
* In the "plug-in" (the assembly which IMPLEMENTS the interface) do the same thing, Add Reference->Project References->Select the assembly which defines the interfaces.
To explain this bit. The compiler needs to know where these Dlls are for the linking stage so what happens when you add a project based reference is that Visual Studio will make sure an up-to-date copy of the appropriate assemblies are in your bin folder. If you use a non-project based reference you can get into trouble.
If you follow the above points, assuming your "usings" are correct too your app will build and assuming the path to the dynamically loading assembly is correct the whole thing will work. (Don't forget to test for a "FileNotFoundException")...
Hope that's a bit more help...
I __AM__ going to write an article about this issue!
Cheers
Shaun
|
|
|
|
|
Thanks for the reply Shaun.
The way my app is set up right now is that I have a forms app where the interface definitions are part of the form app. Meaning that the interface definitions will be part of the app exe. The interface def are not part of their own assembly. The implmentation of the interfaces are indeed in another assebly. I have already referenced the assembly to main app but this does not solve the problem. Originally I did not have this set up, but then I referenced the dll to the host app, but nevertheless the assembly cannot find the interface definition. I am unclear as to what further steps I can take to solve this problem.
|
|
|
|
|
Ahhhh! Now I'm with you!!
You can't do it that way. You need to put your interfaces in a separate assembly so that they can be shared and accessed by both EXE and DLL without the EXE needing to know anything about the DLL.
You can't make the assembly reference the EXE project, that just won't work.
Before .NET you could possibly have included another copy of the .cs file that defined the interface in the DLL but because types are best accessed as fully-qualified-names you won't really get away with that.
So, to recap.
The standard (if indeed, THE correct) way to do what you need to do is to mave your interface definitions from the EXE into a separate dll then reference that project in both the EXE and DLL project.
Shaun
|
|
|
|
|
Yep that did the trick!! Thanks so much for your help!! It is really appreciated.
But I don't understand why the interface needs to be in a separate assembly. I figured that by putting the interface in the same namespace as the user of the interface they would be able to reference each other. What is the concept behind putting the interface in a separate assembly. Or can you give me a brief explanation of why this is the correct architecture.
Thanks again for your help.
|
|
|
|
|
No Probs...
In terms of Interfaces and namespaces I'll try to explain...
Just because you put a bunch of types in different assemblies into the same namespaces doesn't mean that those types are merged together into one namespace.
When you add a reference to another assembly or project the namespaces of that assembly of project becomes accessible to the exe or dll making the reference. The thing is, if you're typing code and using intellisense the IDE merges the namespaces for you but if you look in object browser I don't think they are. Basically the key to accessing code in another assembly is in the references not the namespaces. (That probably makes no sense at all )
As far as the separate dll for Interfaces I'll try to chuck some words down...
There are two reasons: one is architectural good practice, the other is a physical considerations.
Architectural- Good code design dicatates separating 'interface' from 'implementation' everywhere possible, from 'GUI' and 'Business code', to 'class definitions' and 'implementation'... With interfaces (as in public interface foo{} ) you might specify a bunch of them for your application and insist that any part of the system that uses other parts of the system do so using interfaces. The advantage of this is that you can make your code modular and extensible without much effort.
For example you could have a text editor which has a bunch of import filters which all have to support ITextFilter... in future you might want to add new ones which is no problem so long as the new filters support ITextFilter.
Physical- the physical reasons are to do with the old references. If you have a set of assemblies with intefaces and code together then you want to create new code that implements those interfaces too (say on a remote machine for example) you would have to copy all of the dlls with code onto the other machine in order to provide the inteface definition. This is BAD... the best way is to have a small assembly which defines interfaces and have clients and servers reference that. It's also a convenient place to store them too for maintenence.
The other limitation in your case was that your interface was defined in your exe which under .NET is a bit of a no-no, as project references only work with .dll type assemblies.
Sorry if that was patronising (or wrong ) I was kinda in the zone!!
Shaun
|
|
|
|
|
Thanks for that Shaun. Its a little clearer now.
|
|
|
|
|
IrvTheSwirv wrote:
If you follow the above points, assuming your "usings" are correct too your app will build and assuming the path to the dynamically loading assembly is correct the whole thing will work. (Don't forget to test for a "FileNotFoundException")...
I got a question on this issue. Say my EXE looking for the DLL's. They are properly referenced in the project, what if the DLL's (assemblies) are missing physically at runtime. What's the order of searching for this assemblies? ex: search in local directory, if not search in the GAC....
"FYIFV"
Pin made and worn by many Microsoft employees after the company went public. It means, "F*ck You I'm Fully Vested" This signature was created by "Code Project Quoter".
|
|
|
|
|
Here's the answer to that one... from the .NET SDK
You can make a dynamic reference to an assembly by providing the calling method with only partial information about the assembly, such as specifying only the assembly name. In this case, only the application directory is searched for the assembly, and no other checking occurs. You make a partial reference using any of the various methods for loading assemblies such as System.Reflection.Assembly.Load or AppDomain.Load . If you want the runtime to check the global assembly cache as well as the application directory for a referenced assembly, you can specify a partial reference using the System.Reflection.Assembly.LoadWithPartialName method.
So as usual, it depends!
Cheers
Shaun
|
|
|
|
|
Thx Shaun.
If I want to check for the assemblies in my code, where I have to keep the code?
If the assemblies are missing, I want the app to end gracefully instead of crash. BTW, Any code snippet for this?
I want to do like this:
Retrieve all the assemblies the EXE requires.
Find the assemblies in local directory.
If they are not there, then show a error and end the app.
Never take a problem to your boss unless you have a solution. This signature was created by "Code Project Quoter".
|
|
|
|
|
IMHO i think a better approach would be to just handle the FileNotFoundException when you dynamically load the assemblies... but obviously you might know of a good reason to implement what you are describing!
|
|
|
|
|
IrvTheSwirv wrote:
i think a better approach would be to just handle the FileNotFoundException when you dynamically load the assemblies...
Thx Shaun.
Let me ask the question again..
I don't want to dynamically load the assemblies.
When the EXE tries to load the private assemblies (the DLL's EXE requires), if that assembly is not found it will throw the "FileNotFoundException" (Just-In-Time dialog) to the user.
Instead of that dialog, I want to catch that exception and display my version of error message and end the application gracefully.
Now where should I catch that exception?
Never take a problem to your boss unless you have a solution. This signature was created by "Code Project Quoter".
|
|
|
|
|
Many Many Apologies Kant...
I was getting tied up with the other issues in this thread as there seems to be a double stream to it... now that I've re-read I can answer your quezzie!!
The exception will be thrown the first time the type in the DLL is requested by the EXE as the runtime will attempt to load the assembly and create the object.
What I would do is either find the point in the execution where the types are first loaded and wrap that in the old try catches
OR
do a quick instantiation of a known class, wrapping it in a try catch for each of the DLLs..
OR
create a simple class in each assembly (maybe with a simple static call) and try to call it...
OR if none of those are suitable...
You could add entries into your App.Config file which lists the dlls you require to exist in your app folder and just do a DirectorySearch...
I Dunno... it's tricky!!
Shaun
|
|
|
|
|
IrvTheSwirv wrote:
What I would do is either find the point in the execution where the types are first loaded and wrap that in the old try catches
That happens at this point.
Application.Run(new Form1()) in Main().
Thanks Shaun, those were excellent suggestions.
Never take a problem to your boss unless you have a solution. This signature was created by "Code Project Quoter".
|
|
|
|
|
I already did like this to retrieve the modules needed by app. I was shocked know that it loads 94 DLL's...
ArrayList arrayList = new ArrayList();<br />
<br />
foreach (ProcessModule module in Process.GetCurrentProcess().Modules) <br />
{<br />
arrayList.Add(module);<br />
Debug.WriteLine(module.FileName);<br />
}
From this 95 DLL's, I want to know about 2 DLL's (assemblies) only. (Shown as Bold in the following list) How to do that?
C:\Code Project Quoter\CodeProjectQuoter\bin\Debug\CodeProjectQuoter.exe
C:\WINDOWS\System32\ntdll.dll
C:\WINDOWS\system32\mscoree.dll
C:\WINDOWS\system32\KERNEL32.dll
C:\WINDOWS\system32\ADVAPI32.dll
C:\WINDOWS\system32\RPCRT4.dll
C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\mscorwks.dll
C:\WINDOWS\system32\USER32.dll
C:\WINDOWS\system32\GDI32.dll
C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\MSVCR70.dll
C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\fusion.dll
C:\WINDOWS\system32\SHELL32.dll
C:\WINDOWS\system32\msvcrt.dll
C:\WINDOWS\system32\SHLWAPI.dll
C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.10.0_x-ww_f7fb5805\comctl32.dll
C:\WINDOWS\system32\comctl32.dll
c:\windows\microsoft.net\framework\v1.0.3705\mscorlib.dll
C:\WINDOWS\system32\ole32.dll
C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\diasymreader.dll
C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\mscorsn.dll
C:\WINDOWS\System32\uxtheme.dll
C:\Program Files\Avant Browser\SysHook.dll
C:\WINDOWS\system32\oleaut32.dll
C:\WINDOWS\System32\SynTPFcs.dll
C:\WINDOWS\system32\VERSION.dll
C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\MSCORJIT.DLL
c:\windows\assembly\gac\system.windows.forms\1.0.3300.0__b77a5c561934e089\system.windows.forms.dll
c:\windows\assembly\gac\system\1.0.3300.0__b77a5c561934e089\system.dll
c:\windows\assembly\gac\system.drawing\1.0.3300.0__b03f5f7f11d50a3a\system.drawing.dll
C:\WINDOWS\System32\netfxperf.dll
C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\perfcounter.dll
c:\windows\assembly\gac\system.xml\1.0.3300.0__b77a5c561934e089\system.xml.dll
C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\CorperfmonExt.dll
C:\WINDOWS\System32\PSAPI.dll
C:\WINDOWS\System32\aspperf.dll
C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\aspnet_isapi.dll
C:\WINDOWS\System32\query.dll
C:\WINDOWS\System32\infoctrs.dll
C:\WINDOWS\System32\INFOADMN.dll
C:\WINDOWS\System32\IisRTL.DLL
C:\WINDOWS\System32\WS2_32.dll
C:\WINDOWS\System32\WS2HELP.dll
C:\PROGRA~1\MI6841~1\MSSQL$~1\Binn\sqlctr80.dll
C:\PROGRA~1\MI6841~1\MSSQL$~2\Binn\sqlctr80.dll
C:\PROGRA~1\MI6841~1\MSSQL\BINN\SQLCTR80.DLL
C:\WINDOWS\System32\snprfdll.DLL
C:\WINDOWS\System32\STAXMEM.dll
C:\WINDOWS\System32\perfdisk.dll
C:\WINDOWS\System32\perfnet.dll
C:\WINDOWS\System32\NetApi32.Dll
C:\WINDOWS\System32\perfos.dll
C:\WINDOWS\System32\perfproc.dll
C:\WINDOWS\System32\rasctrs.dll
C:\WINDOWS\System32\rasman.dll
C:\WINDOWS\System32\rsvpperf.dll
C:\WINDOWS\System32\smtpctrs.DLL
C:\WINDOWS\System32\SMTPAPI.dll
C:\WINDOWS\System32\winspool.drv
C:\WINDOWS\System32\tapiperf.dll
C:\WINDOWS\System32\tapi32.dll
C:\WINDOWS\System32\rtutils.dll
C:\WINDOWS\System32\WINMM.dll
C:\WINDOWS\System32\Secur32.dll
C:\WINDOWS\System32\Perfctrs.dll
C:\WINDOWS\System32\iphlpapi.dll
C:\WINDOWS\System32\MPRAPI.dll
C:\WINDOWS\System32\ACTIVEDS.dll
C:\WINDOWS\System32\adsldpc.dll
C:\WINDOWS\system32\WLDAP32.dll
C:\WINDOWS\System32\ATL.DLL
C:\WINDOWS\System32\SAMLIB.dll
C:\WINDOWS\System32\SETUPAPI.dll
C:\WINDOWS\System32\perfts.dll
C:\WINDOWS\System32\WINSTA.dll
C:\WINDOWS\System32\UTILDLL.dll
C:\WINDOWS\System32\w3ctrs.dll
C:\WINDOWS\System32\wbem\wmiaprpl.dll
C:\WINDOWS\System32\loadperf.dll
C:\WINDOWS\System32\wbem\wbemcomn.dll
C:\WINDOWS\System32\NTMARTA.DLL
c:\code project quoter\codeprojectquoter\bin\debug\quoteslibrary.dll
c:\code project quoter\codeprojectquoter\bin\debug\htmleditor.dll
c:\windows\assembly\gac\microsoft.mshtml\7.0.3300.0__b03f5f7f11d50a3a\microsoft.mshtml.dll
c:\windows\assembly\gac\accessibility\1.0.3300.0__b03f5f7f11d50a3a\accessibility.dll
C:\WINDOWS\WinSxS\x86_Microsoft.Windows.GdiPlus_6595b64144ccf1df_1.0.10.0_x-ww_712befd8\gdiplus.dll
C:\WINDOWS\System32\CLBCATQ.DLL
C:\WINDOWS\System32\COMRes.dll
C:\WINDOWS\System32\mshtml.dll
C:\WINDOWS\system32\URLMON.DLL
C:\WINDOWS\System32\mlang.dll
C:\WINDOWS\System32\msimtf.dll
C:\WINDOWS\System32\MSCTF.dll
C:\WINDOWS\system32\WININET.dll
C:\WINDOWS\system32\CRYPT32.dll
C:\WINDOWS\system32\MSASN1.dll
Never take a problem to your boss unless you have a solution. This signature was created by "Code Project Quoter".
|
|
|
|
|
Hello All,
I was wondering if there is an easy way to create the event handlers for objects. I know that simply clicking on them brings up their default event handler, such as Form_Load. Is there a way to do this for say, right_click, or any of the other events of any object through the ide? Rather than just typing it in.
Thanks,
Ryan
|
|
|
|
|
Perhaps you have missed to look the VS.NET events.
open up your project in VS.NET 2002/3
click F4 or Click "View" -> Properties Window"
now go click any UI,
and click on any Control of your wish
In properties window you will see lightning bolt (2n'd after A-Z sorting order)
click there on Lightning bolt which is event and its the destination of all events
Paresh
|
|
|
|
|
|
I have Master-Detail datagrid. The detail datagrid is embedded in the Master datagrid. In the detail datagrid I want to implement paging ,sorting etc. I have addes the event handlers delegates manually. For some reason the pageindexchanged or sort events for the detail datagrid. Does anyone know of this behaviour? I saw a lot Master-Details datagrids on the internet, nobody seems to have implemented paging-sorting for details grid embedded within a datagrid. thanks
Madhuri Mittal
|
|
|
|
|
have you seen the initial MSDN Datagrid sample, its parent->child relation ship of tables based datagrid
so if you click on + sign you get the detail(child)datagrid.
well its actually one grid only.
but reffer to
Datagrid Question And Answers
Paresh
|
|
|
|
|
How can I host an Internet Explorer window inside of a windows form?
Like what the autocad installer is like....
/\ |_ E X E GG
|
|
|
|