In XAML, a custom namespace can be imported with an xmlns directive:
xmlns:custom="clr-namespace:GreatStuff"
In C#, that namespace can be imported with
using GreatStuff;
Moreover, evaluation of that namespace based on the global (root) namespace can be enforced as follows:
using global::GreatStuff;
How can I enforce evaluation based on the global namespace in XAML?
Background:
I am facing the (admittedly slightly obscure) situation that there is such a namespace global::GreatStuff, which contains a WPF control class named ... GreatStuff (i.e. fully qualified, that's global::GreatStuff.GreatStuff in C#). In the same namespace, I want to use that control in a WPF window.
Interestingly, in this constellation, I cannot use the Name/x:Name attribute on any controls of type global::GreatStuff.GreatStuff in my XAML file for the window:
The type name 'GreatStuff' does not exist in type 'GreatStuff.GreatStuff'. (CS0426)
Note that the very same file compiles fine if I do not specify a Name/x:Name attribute!
Now, why should the compiler assume that by setting a Name/x:Name attribute, I am trying to access something called GreatStuff.GreatStuff.GreatStuff?
The answer can be found by examining the .g.cs file generated from the window XAML file. In that file, the XAML snippet
<custom:GreatStuff x:Name="stuff"/>
gets compiled to the following C# snippet:
internal GreatStuff.GreatStuff stuff;
That is, the fully-qualified name is used, but without the explicit global namespace marker.
Of course, as a field in a class in namespace global::GreatStuff, all of this is wrapped in
namespace GreatStuff {
And so, the poor C# compiler cannot help but assume that stuff is supposed to be of a type global::GreatStuff.GreatStuff.GreatStuff. This could be avoided if in
xmlns:custom="clr-namespace:GreatStuff"
I could enforce that any mentions of that namespace prefix could be converted while enforcing the global namespace.
For reasons external to this question, changing the namespace and/or class names is not an option here.
This issue only occurs when all of the following are true:
You have a class with an identical name as the namespace containing it.
Within that same namespace, you have a xaml file with an instance of an object that is also declared within that namespace.
That specific object instance is given a Name or x:Name attribute.
If you cannot modify anything to make any one of those conditions false, then you are working with some very serious restrictions.
As far as I know, this is a limitation of the xaml compiler, and you will need to contact Microsoft about resolving it. The only other thing I can think of would be to try to work around it with a custom build process that builds xaml, allows you to edit the generated files, then builds the code. That would require some research to figure out how to set up.
Related
I have a compiled class library with a root namespace Protege.MyLibrary.
It has a few root types, for example, CommonlyNamedType.
When I add the library to my consuming application, I'd like, for clarity in some situations, to be able to specify variables as:
using Protege;
...
MyLibrary.CommonlyNamedType oMyType = new MyLibrary.CommonlyNamedType;
rather than
using Protege.MyLibrary;
...
CommonlyNamedType oMyType = new CommonlyNamedType;
The former doesn't compile, indicating for the namespace Protege "Using directive is unnecessary", and that is can be removed.
This seems bizarre as I could go the other way and add additional namespaces, such as Protege.MyLibrary.AnotherNamespace.
I seem to be able to do this 100% okay in VB.NET - using either or both Imports Protege and/or Protege.MyLibrary and even optionally qualifying types with redundancy. But not in C#.NET.
I have had a good look around SO and other places and haven't seen an explanation for this behavior. Any ideas?
You can statically import a class like
using static System.IO.File;
It doesn't support for class, you need to use normal using for import the namespace.
Unfortunately, due to issues that are frustratingly out of my control, I'm forced to use components with namespaces which I cannot change. Because of the way they have structured them, it's causing collisions in the generated code-behind.
Again, unfortunately, I do not have access to the code which defines these namespaces so they cannot be changed. Down-voting this does not help anyone, especially without a reason/explanation. Also, I've also tried demonstrating the issue to the owners explaining why this is a very bad design, but I've been told for other reasons, changing them is not an option, so I'm forced to find a work-around.
Here's a simplified example to illustrate the issue. Consider a solution with two projects, a 'Core' library, and the consuming application:
Items in 'Core' Library
ModelA (Namespace: SomeFeature.Core.Models)
ModelB (Namespace: SomeFeature.Core.Models)
**Items in 'ConsumingApp' (References 'Core') **
MainWindow (Namespace: ConsumingApp.SomeFeature)
TestControl (Namespace: SomeFeature.Controls)
The cause of the collision can be explained in three steps:
SomeFeature is both the root of one namespace, and a child of another
TestControl is defined as being in the rooted version of the namespace (same as the library), not the one MainWindow is in.
Code-generation ends up placing the generated variables for those XAML elements in the namespace scope of MainWindow, not that matching what's actually in the XAML.
Now if these were manually-defined variables in non-generated code-behind, dealing with this is easy. By simply adding the prefix global:: it 'roots' the namespace you're typing, thus removing all ambiguity.
namespace ConsumingApp.SomeFeature{
public partial class MainWindow{
// Note the 'global::' prefix
global::SomeFeature.Controls.TestControl MainTestControl { get; set; }
}
}
The above will ensure that it always resolves relative to the global SomeFeature namespace and never the nested ConsumerApp.SomeFeature namespace. Pretty straight forward.
However, the auto-generated code-behind from the XAML parser doesn't include that global:: prefix, so in the generated code, you actually get this:
namespace ConsumingApp.SomeFeature{
public partial class MainWindow{
// Note: without the 'global::' prefix, this resolves to
// 'ConsumingApp.SomeFeature.Controls.TestControl'
// which doesn't actually exist, causing the mentioned issue.
SomeFeature.Controls.TestControl MainTestControl { get; set; }
}
}
Which results in this error:
Error CS0234 The type or namespace name 'Controls' does not exist in the namespace 'ConsumingApp.SomeFeature' (are you missing an assembly reference?)
As noted in the code comments, this is because it's not looking for this class path...
SomeFeature.Controls.TestControl
but rather this one:
ConsumingApp.SomeFeature.Controls.TestControl
which doesn't exist, ergo the error.
The fix would be to somehow get the auto-generated code to explicitly output the global:: but I don't know how to do that, or even if it can be done.
Things I've tried:
Arguing for them to change their namespaces! (I lost!)
Explicitly referencing the assembly in the XAML import:
Defining aliases in the non-generated code-behind
Searching for aliases in the XAML world (not found)
Avoiding naming the element, and instead manually searching for the control via other properties. (Horrible, but this does work!)
So is there anything that can be done here to get the code-generator to include the 'global::' prefix, or is there another way to do this?
The unity documentation recommend to use namespaces to organize your code, avoid extended class name, and make more maintainable code.
ControlerCameraAction becomes Controleurs.Cameras.Action and CameraAction becomes Cameras.Action.
However in Unity editor you can't see your namespaces, only the last class name, and this can be confusing since some class have now same name.
Editor shows now Action and Action
So how to use namespaces in Unity?
Am I doing something wrong?
So how to use namespaces in Unity ?
Like you did, basically. Namespaces are used in code, not in the editor. The main problem of Unity is the way that scripts are treated. Scripts get compiled internally into debuggable IL-Code.
But in the editor itself, they are always named by their filenames, which are forced to be the same as the class name.
This is the reason you don't see your whole type-name (namespace + classname), but always the classname alone.
Am i doing something wrong ?
No, you aren't. As far as I remember, there is no way to display the classname instead of the filename in the editor, since the displayed data is determined by the meta-files that Unity generates.
So tl;dr:
You are doing it right and there is no way to display the namespaces in the Editor.
I'd suggest you should sort your scripts into folders and use the AddComponentMenu-Attribute to organize your code physically according to your namespaces. This is the same pattern that is used by Microsoft.
Easy way is to think in namespace how file folder. You assign your desired name avoiding similar name to systems and unity namespace. Each namespace inside another namespace is similar to navigate inside a folder inside another folder.
Ussually this start with your company name or your plugin name:
namespace mycompany_name
{
namespace myplugin_name
{
}
}
or
namespace myplugin_name
{
//part name i.e. Networking, Utils, Database or similar ramification
namespace myplugin_part_name
{
}
}
Later you reference to it in another script with "using":
using mycompany_name.myplugin_name
The unity documentation recommend to use namespaces to organize your
code, avoid extended class name, and make more maintainable code.
Yes !
ControlerCameraAction becomes Controleurs.Cameras.Action and
CameraAction becomes Cameras.Action.
Yes, and no.
The idea behind namespaces is organization not just simple use this feature called namespaces. And that organization should follow a logic. If every class has a different namespace then you will have to import as many namespaces as classes that you will use in your code.
You can think in terms of 'modules' or maybe see if a layered architecture can be useful for you.
If you have ControllerCameraAction and CameraAction, you can a.- use the namespace Cameras for both (then you will have Cameras.CameraAction and Cameras.ControllerCameraAction) , b.- if you have a layered architecture (like MVP, MVVM, or some more DomainDesign Driven, etc.) you can have namespaces using the layer name and the module. (then you will have something like Presentation.Cameras.ControllerCameraAction, Domain.Cameras.CameraAction and this can help you to follow an Onion architecture).
The syntax for namespaces are like this:
namespace Domain.Cameras
{
public class CameraAction
{
}
}
And you use them with using directive
using Domain.Cameras;
namespace Presentation.Cameras
{
public class ControllerCameraAction
{
private CameraAction cameraAction;
...
}
}
More about namespaces here!
By default all classes that don't have an explicit namespace belong to global namespace, so even when you are not writing any namespace you are using one.
Unity will not make any difference between namespaces, this is more a c# characteristic. And it helps with organization, separation of concerns principle, and avoiding name conflicts too, but in the last instance, your class names should still be representative and clear enough to understand what that class does. If you see Camera.cs and Camera.cs it's really hard to see what class does what. If you open those files and see the namespace/code/folder where they are that will help, but the idea is save those extra seconds/cognitive load and just be more explicit with your names.
As a complement here you can see another interesting discussion about namespaces use.
I have the following two files:
IGlobalApiProvider.cs
using System.Collections.Generic;
using Vert.Slack;
namespace Vert.Interfaces
{
public interface IGlobalApiProvider
{
List<Im> ImList();
}
}
And the corresponding implementation: SlackApi.cs
using System.Collections.Generic;
using Vert.Interfaces;
namespace Vert.Slack
{
public class SlackApi : IGlobalApiProvider
{
public List<Im> ImList()
{
...
}
}
}
Now, Intellisense is telling me that when I use IM in IGlobalApiProvider it's resolving to Im, which is defined in a file named RtmStart.cs which has no namespace declaration. When I use IM in SlackApi.cs, it's resolving to Vert.Slack.Im which is defined in the Vert.Slack namespace in a file named Im.cs. The weird behavior alerted me to the redundant definition, so I removed it and things are working fine.
However, I'm confused about why Visual Studio behaved differently in these two ways. I can tell something was scanning for the class names in a different pattern in the two situations. I can also tell that being used in the same namespace vs being used in a class that uses the namespace seems to be the trigger. What I don't know is what mechanism controls the logic behind this behavior.
Can anyone shed light on this?
Everything you see is contained in Vert.dll, which consists of one project, Vert.csproj
Link to the four files mentioned in this post as they existed at the time of writing.
This has to do with the difference between the global and Vert.Slack namespaces.
The compiler looks for the most explicit namespace with the proper class defined.
In this example, when the compiler looks for the definition of Im in IGlobalInterfaceProvider.cs, there is no namespace defined (or used) in this file that contains the class, but Im is also defined in this file - which is declared in the global namespace.
When the compiler looks for the definition of Im in SlackApi.cs, Im is found in the explicit Vert.Slack namespace, and utilizes that class.
The answer here is a similar topic and may provide more insight.
This may be related to the fact that your namespaces are in the wrong place ;-)
http://www.stylecop.com/docs/SA1200.html
This answer here gives a good explanation: Should 'using' statements be inside or outside the namespace?
I have defined a user control, ExpressionControl, under the namespace:
TriggerEditor.UserControls
I have a form, "IfEditor", under the namespace:
TriggerEditor.Forms
When I add an instance of my control to the form (naming it expCondition), the following code is generated in the Designer to create the control:
this.expCondition = new TriggerEditor.UserControls.ExpressionControl();
This results in the following compilation error:
The type name 'UserControls' does not exist in the type 'TriggerEditor.Forms.TriggerEditor'
I don't understand why it is looking in "TriggerEditor.Forms.TriggerEditor"; that's not what the code says. Now, I can resolve this error manually by modifying the line, removing the "TriggerEditor." that preceeds "TriggerControls", as such:
this.expCondition = new UserControls.ExpressionControl();
This satisfies the compiler, however I obviously don't want to do this every time I add an instance of my ExpressionControl to a form. How do I avoid this situation?
It looks like you might have a TriggerEditor class within the TriggerEditor.Forms namespace; is this the case?
If so, because the TriggerEditor class is within your current namespace, you are "closer" to this class, and therefore it is looking for a subclass.
Avoid using the same name for a class and a namespace!?
Apparently, in the namespace TriggerEditor.Forms, you have a class named TriggerEditor in the same namespace as your IfEditor class.
So, when looking for TriggerEditor.UserControls.ExpressionControl, the compiler looks in the TriggerEditor class (which is in the same namespace, so closer) instead of the TriggerEditor namespace...
Normally, to avoid that, you would use a namespace alias qualifier, but being in a Designer generated class, you can't really control that.