views:

151

answers:

3

I have library code that uses ICSharpCode.SharpZipLib under the hood to make it easy to use ZIP files as data sources when running integration tests.

As it stands, if I reference my library from another project, the other project will compile just fine, but when it accesses the code that uses SharpZipLib, I get an exception for it not finding the zip library:

failed: System.IO.FileNotFoundException : Could not load file or assembly 'ICSharpCode.SharpZipLib, Version=0.85.5.452, Culture=neutral, PublicKeyToken=1b03e6acf1164f73' or one of its dependencies. The system cannot find the file specified.

If the types in my library derived from a class in SharpZipLib, it'd generate a compile error CS0012. What other ways are there for triggering a CS0012, so that using code that requires SharpZipLib (but doesn't clearly indicate it) would cause consumer code to fail compilation?

I've had similar problems in the past when I've used libraries like DeftTech.DuckTyping under the hood. I'd add my library code to a new project, start working, compile, run, and then suddenly hit an edge case that I'd used duck typing to get around and get a runtime error.

What I'd most like is to have the same behavior as if I'd derived from a type in the 3rd-party library, so that a reference to my derived type generates a CS0012:

The type 'type' is defined in an assembly that is not referenced. You must add a reference to assembly 'assembly'.

A: 

You only get compiler errors if you are DIRECTLY interacting with libraries that aren't referenced.

If you use other libraries that internally use a third party library then you will never get a compiler error. The reason is this just doesn't make much sense having a compile error because:

  • It does not affect compiling at all, so why a compiler error?
  • Your application MIGHT run correctly, because there is no guarantee the third-party library EVER gets called.
  • It might actually break several libraries, that e.g. do reference external libraries for debugging, but just don't ship them for release.

Edit: If your problem is that you are forgetting about the third-party library you can simply reference it directly from your application even if you never use it. Then e.g. Visual Studio will automatically copy it to your output bin folder and includes it in setups, and so on.

Foxfire
I quite agree that it shouldn't cause a compiler error under normal circumstances. But if I know that any use of a specific type requires a separate library, it'd be wonderful to fall into the pit of success you get from a compiler error telling you so.
Thomas G. Mayfield
Did you already read my edit? Just add the reference and you are good to go.
Foxfire
+1  A: 

If you're seeing this while in Visual Studio it's probably because the ICSharpCode.SharpZipLib.dll isn't being copied to the build folder of your "other" project.

So this won't be a problem when you distribute your library for consumption by third parties because the ICSharpCode.SharpZibLib.dll will be in the same folder as your library.

During development and testing though it can be a bit of a hassle. Generally when setting up a multi-project solution I just have all the projects target their Output folder to a single solution-wide Build folder. That way all the dependencies are copied to the same location for testing.

Paul Alexander
While they're all my projects, they're not all part of the same overall project. The references are to compiled and released DLLs from the build server. It's not a huge problem to have, I just started thinking on it with this SharpZipLib example, because I remembered headaches caused months and months after writing the code that worked with DeftTech.DuckTyping. I'd love for the dependency to be documented in a way that the compiler can tell me when I forget a year from now.
Thomas G. Mayfield
I don't particulary like the single output folder solution because it completely breaks and creates very hard-to-find errors if you use a project in multiple solutions.
Foxfire
A: 

My goal being to fail as quickly as possible when I know a reference is required, I guess I'm left with three options:

  1. Derive from a type in SharpZipLib. There are a couple of interfaces I could explicitly implement, but I really don't like this option. This would misrepresent the purpose of the class, however lightly.

  2. Use a type from SharpZipLib in the static constructor for the class I know consumes it. This makes it throw an exception once anything tries to use my classes.

  3. Don't change anything. If code enters a path that requires SharpZipLib, it'll fail at that point if a reference doesn't exist.

I'm going with option 3 for this case, but option 2 might be the right choice in other circumstances.

The previous example I'd mentioned with DeftTech.DuckTyping only occurred in edge cases, when forms were displayed to the user and my tools could not find a way to store and restore customizations to controls on the screen without duck typing to an interface (DevExpress controls all have the same method names for storing and restoring layouts, but don't implement a common interface).

But for this testing data file utility, it's not an edge case but a common one, and its primary usage will be in integration tests, which will be run frequently.

Thomas G. Mayfield