views:

304

answers:

5

Hi

I have a solution called Tools that has three projects in it; Tools, PerecentageBar, MessageBox. Each of these projects is part of the Tools assembly.[In the properties page of each I have set the AssemblyName to MyCompany.Tools.Controls].

I have in Tools Project:

namespace MyCompany.Tools.Controls
{
     public class MyPictureBox : PictureBox
     {} 
}

And in the MessageBox project.

namespace MyCompany.Tools.Controls
{
     public class MyMessageBox : Form
     {} 
}

And in the PercentageBar project

namespace MyCompany.Tools.Controls
{
     public class PercentageBar: UserControl
     {} 
}

This solution is built and a MyCompany.Tools.Controls.dll created.

In another solution, I have a project called MapperTool.

namespace MapperTool
{
    public class MapperToolFacade : IDisposable, IDiagService
    {}
}

In this project I add a reference to the dll above AND add a using statement thus:

using MyCompany.Tools.Controls;

All good so far, however. In this project I can only 'see' and use MyPictureBox with the above using statement. The other types MyMessageBox and PercentageBar are not available.

Why is this?

EDIT: Investigation shows that the other types are there and under the namespace MyCompany.Tools.Controls. However, looking in class view they are not listed in the MyCompany.Tools.Controls assembly. Instead they are organised thus:

MyCompany.Tools.Controls                  (assembly)
    MyCompany.Tools.Controls              (namespace)
        MyPictureBox                      (type)

PercentageBar
    MyCompany.Tools.Controls
        PercentageBar

MyMessageBox
    MyCompany.Tools.Controls
        MyMessageBox

So I guess the next question is, if I have specified the assembly name as MyCompany.Tools.Controls in each project why have the second two projects been built as an assembly with a different name? [ The dll in the output directory does however have the naem MyCompany.Tools.Controls.dll]

Also, I want to creat all my controls in the MyCompany.Tools.Controls namespace and build them into a single MyCompany.Tools.Controls assembly such that I can add just this reference to any other project that needs to use them.

It would appear from what is happening above that each seperate tools project in my MyCompany.Tools.Controls solution would have to be built into a unique assembly and that each would have to be referenced individually...?

The problem was my understanding of projects and assemblies. It would appear that it is not possible to have the 3 projects build into one assembly. Each must build it's own assembly - I will then have to use a merge tool to combine them into one assembly.

+3  A: 

Use the using directive.

MSDN: using Directive (C#)

So in your case, it would be: using MyCompany.Tools -- this goes with the other using statements that were auto-generated in the source file.

Edit: try using Controls = MyCompany.Tools.Controls. I don't generally reference namespaces in code using an alias unless I absolutely have to, but I think this should work.

Jon Seigel
Nope tried that. Using MyCompany returns an error - namespace not found. I think maybe it is due to how the solution that contains MyMessageBox is setup. Perhaps the assembly name. I have a similar problem whereby only controls in the project with the same name as the solution are seen when this solution is referenced by another.
Kildareflare
+2  A: 

Have you added a reference to that assembly into your new project ?

JonH
+2  A: 

Namespaces are not exported over a reference boundary. Only types (and functions). In order to 'see' the MyCompany namespace, you would need to add a type (a class) directly underneath that namespace.

Matt Brunell
+1  A: 

Edit - based on your follow-up comments, I'll hazard a guess about what's wrong:

Assembly1 defines the class MyMessageBox in the namespace MyCompany.Tools.Controls.

Assembly2 references Assembly1 and defines at least one class in the namespace Controls. That is, the class declaration looks like this:

namespace Controls {
    public class MyControl {
        // ...
    }
}

Assembly3 references the compiled Assembly2.

If this is the case, Assembly3 can see the namespace Controls but not MyCompany or MyCompany.Tools because neither of those namespaces are used by a class in the referenced assembly. The project's default namespace it is only used to create the default for new class files and to generate namespaces for embedded resources - it does not actually exist in the assembly unless you define a type that uses it.

If I've guessed right, you should add a type to Assembly2 within the MyCompany.Tools.Controls namespace. This will make the top-level namespaces visible to Assembly3.

If Assembly2 contains the other portion of the partial class MyMessageBox, it will need to be declared within the same namespace as the other portion.


That looks like it should work (and does in my tests). In the meantime, try changing it to:

namespace MyCompany.Tools.Controls
{
    public partial class MyMessageBox : Form {}
}

It shouldn't make any difference, but it is a more idiomatic way to define nested namespaces in C#.

Jeff Sternal
Kildareflare
Just to get this straight: all three projects (Tools, ToolA, and ToolB) are in a single solution ("Tools"), but only the "Tools" types show up in the class view? Or the ToolA and ToolB projects are in a seperate solution referenced by the Tools project (as dlls)? Are their types visible in the class view, under the "Tools" project's Project References?
Jeff Sternal
All three projects in single solution. In another solution I add a reference to the dll built by the first solution and add a using statement for the namespace. In the second solution only Tools shows up in class view. I want the first solution to contain all my controls, under the one namespace. Then reference this in other solutions.
Kildareflare
And what is in the "Tools" project that you're referencing from the second solution? Are there one or more classes declared like this: `namespace Controls { public MyControl { ... } }`? Does that project include any classes explicitly declared within the MyCompany.Tools.Controls namespace? (or in either of those?) Incidentally, feel free to update your question with this information so that it's more visible to other people that might be able to solve it!
Jeff Sternal
As an aside. They do appear in class view in the containing solution - solutionA. Just not in solutionB which references solutionA.
Kildareflare
Tools project within Tools solution contains public MyPictureBox, MessageBox project within same solution contains public MessageBox, PercentageBar project contains public PercentageBar. From the other solution I can create a MyPictureBox but MessageBox and PercentageBar are unknown types.
Kildareflare
I've updated my answer with my best guess.
Jeff Sternal
Thanks Jeff, I've updated the question now and added as edits as I think have got to the root of the problem - my understanding of projects and assemblies.
Kildareflare
Excellent! The absence of static linking in C# is one of those things that just goes without saying ... until it doesn't. Depending on the scenario, I would usually just build all the controls in a single assembly, or I'd be prepared to reference all three in client assemblies. If neither option sounds good, check out this stack overflow topic: http://stackoverflow.com/questions/39116/linking-statically-in-c. The first answer discusses a tool for merging assemblies.
Jeff Sternal
A: 

To help clear up the issue you can use the Class Explorer in Visual Studio to inspect the namespace the class is in. I would first verify that MyMessageBox is in fact in the namespace you believe it to be.

Then, if it's as expected, you should focus on your second project. Is your other class within the MyCompany.Tools namespace? Does it, by chance, declare classes name MyCompany or Tools (visual studio can trip up if a local class conflicts with an imported namespace).

STW
Ok, the type is not in Class explorer where i expect. My solution is called CustomControls, there is a project called CustomControls in it and another called MyMessageBox. The later does not apear in the namespace. Do I need to ensure all projects have the same assembly and default namespace in their properties?
Kildareflare