I know nesting of namespaces is allowed in C++/CLI. So my question is if we have something like this:
...
namespace one
{
// blah blah blah
// ...
namespace two
{
// another set of blah blah blah
// ...
}
}
and I need to use some functions and variables in namespace two, do I use:
one::two
or
one.two
Another question is that if I have a statement like
using namespace one;
do I have access to variables and functions in any nested namespaces like
namespace two
I'm asking because, in some programs I have seen (and written), there's something like:
using namespace System;
using namespace System::Text;
using namespace System::IO;
Isn't the System namespace supposed to cover the System::Text and System::IO namespaces?
You need to use
one::two::some_variable_or_function
The . operator is for accessing non-static struct/class members. Static members can then again be accessed through the scope resolution operator ::.
If you only would use using System;, you could access the System::Text functions/variables by
Text::some_function_or_variable
using the parent namespace does not imply importing all sub-namespaces.
Yes, you need use one::two instead of one.two to access symbols in a nested namespace.
If you just using namespace one; you don't automatically have the access to the nested namespace. You'll have to use two::
Example:
namespace one
{
int i;
namespace two
{
int j;
}
}
If you use:
using namespace one;
Your code looks like:
i = 1;
two::j = 2;
If you use:
using namespace one;
using namespace one::two;
Your code looks like:
i = 1; //Compile fails if no "using namespace one".
j = 2;
one::two
or
one.two
You need to use one::two. one.two is the syntax for package access in Java
Another question is that if I have a
statement like
using namespace one;
do I have access to variables and
functions in any nested namespaces
like
namespace two
No, you can use them as two:: instead of one::two::
I'm asking because, in some programs I
have seen (and written), there's
something like:
using namespace System;
using namespace System::Text;
using namespace System::IO;
Isn't the System namespace supposed to
cover the System::Text and System::IO
namespaces?
No, they aren't the same. You have to specify usage of each child namespace.
In general, you use the dot only when you're referring to a member of an instance, and :: everywhere else. So to access stuff in your namespace two, you'd call it one::two::whatever.
As for using namespace System;, it'd import stuff from the System namespace. While System::IO and System::Text are in System, it doesn't import them directly into the current namespace. AFAIK you'd be able to say using namespace System; and then refer to a class within a nested namespace as, say, IO::Stream. But that would get confusing fast, if you use a bunch of namespaces.
1) one::two
2) using a parent namespace doesn't automatically expand any nested namespace.
Related
According to the docs, it seems like there can only be one namespace registered at a time.
xml.etree.ElementTree.register_namespace(prefix, uri)
Registers a namespace prefix. The registry is global, and any existing
mapping for either the given prefix or the namespace URI will be
removed. prefix is a namespace prefix. uri is a namespace uri.
Tags and attributes in this namespace will be serialized with the
given prefix, if at all possible.
But I was curious if anyone knows of some way around this? If there's nothing reasonable, I will switch to lxml.
You can register more than one namespace, just not in a single call to register_namespace().
You'd have to make separate calls to register_namespace() for each namespace.
Example...
import xml.etree.ElementTree as ET
ns_map = {"foo": "urn::foo",
"bar": "urn::bar"}
for prefix, uri in ns_map.items():
ET.register_namespace(prefix, uri)
root = ET.Element(ET.QName(ns_map["foo"], "root"))
ET.SubElement(root, ET.QName(ns_map["bar"], "child"))
print(ET.tostring(root).decode())
Prints...
<foo:root xmlns:bar="urn::bar" xmlns:foo="urn::foo"><bar:child /></foo:root>
Also...
If there's nothing reasonable, I will switch to lxml.
I'd switch to lxml anyway. :-)
The scenario is new and I believe it might be a bug in cpp-winrt module or the vc compiler.
The Problem
1. Create a "windows runtime component" using the cpp-winrt template for universal windows.
2. Note the namespace name defined in the idl file. By default the idl file is named as class.idl.
3. Add a "new standard cpp class" to the project using the class wizard.
4. Put the new class under the same namespace name as defined in the idl file.
5. Build the project.
a. The build should succeed.
6. Use the standard cpp class in the runtime implementation class.
7. Now try to build the project again.
a. The build will fail this time.
The Reason
1. cppwinrt.exe generates source files from the idl file.
2. The runtime implementation class namespace is prefixed by "winrt".
3. The standard cpp class is not prefixed by the namespace "winrt".
4. The vc compiler expects the standard cpp class namespace to start from "winrt"
5. Otherwise the name resolution fails even if you try to use the fully qualified namespace name.
Example runtime idl file
namespace NMLevel1.NMLevel2
{
[default_interface]
runtimeclass Class
{
Class();
void RuntimeMethod1();
Int32 RuntimeMethod2(Int32 arg1);
String RuntimeMethod3(String arg1);
Int32 MyProperty;
}
}
Example standard cpp file
#pragma once
#include <string>
using namespace std;
namespace NMLevel1::NMLevel2
{
class StdCPPClass
{
public:
StdCPPClass();
virtual ~StdCPPClass();
void method1();
int method2(int arg1);
wstring method3(wstring arg1);
};
}
Example runtime class implementation
#include "pch.h"
#include "Class.h"
#include "NMLevel1.NMLevel2.Class.g.cpp"
#include "StdCPPClass.h"
using namespace winrt;
using namespace Windows::Foundation;
namespace winrt::NMLevel1::NMLevel2::implementation
{
void Class::RuntimeMethod1()
{
NMLevel1::NMLevel2::StdCPPClass stdcls;
Uri uri(L"http://aka.ms/cppwinrt");
//printf("Hello, %ls!\n", uri.AbsoluteUri().c_str());
printf("RuntimeMethod1(): Hello, %ls!\n", stdcls.method3(uri.AbsoluteUri().c_str()).c_str());
}
}
NMLevel1::NMLevel2::StdCPPClass stdcls; is not allowed without prefixing the namespace with winrt.
Is this a bug or a design limitation that cannot be overcome?
or How can I use the same namespace 'NMLevel1::NMLevel2' in idl and cpp files?
Name lookup in C++ is fairly involved, especially when namespaces get essentially merged through using declarations. To help the compiler identify the name you want, you'll have to be explicit, and use a fully qualified name (as opposed to a qualified name, as in the sample).
You'll have to change
void Class::RuntimeMethod1()
{
NMLevel1::NMLevel2::StdCPPClass stdcls;
// ...
}
to
void Class::RuntimeMethod1()
{
::NMLevel1::NMLevel2::StdCPPClass stdcls;
// ...
}
Note the leading :: scope resolution, which limits lookup to the global scope (or namespaces introduced into the global namespace through a using declaration). You'll find additional information here: Qualified name lookup.
If I have namespace with two classes. I want to use class from one namespace and I have Resharpner tool. Even I select full qualifies name of my Font class it will use Font from System namespace. How to use label and will it removed debugging capability
using System.Windows.Forms;
using Cy.GlobalSettings.ChartSettings;
but have problem
current namespace is Cy.GlobalSettings.ChartSettingsUC;
Font class has a confilct?
You can rename classes if the class name is the same in both referenced namespace. If both namespace have a class called Font you can create an alias for a namespace or a type:
using System.Windows.Forms;
using Cy.GlobalSettings.ChartSettings;
using CyFont = Cy.GlobalSettings.ChartSettings.Font // This is the full name of the Font class which is causing the conflict.
Font y; // class from System.Windows.Forms
CyFont x; // class from Cy.GlobalSettings.ChartSettings
After this you can use both Font and CyFont in your code without conflicts.
using Directive (C# Reference)
http://msdn.microsoft.com/en-us/library/sf0df423(v=vs.80).aspx
Fully qualified name should work as well.
I have class name called "Address" in two namespaces. Its been two EDMX files, so it holds
different namespace in client side. I have another class "Vendor" and it holds object of "Address" class. In one situation i have to convert from one namespace to another namespace.
How i can achieve this.
You do not cast namespaces, you resolve types by qualifying them with a namespace.
Generally it is a bad idea to have multiple classes with the same name, especially if they are used together somewhere in the application.
It is not possible automatically. Namespace is really just a prefix of name of class. Essentially they are completely different classes with nothing in common.
Unless one Address class is derived from the other one, you cannot cast between the two at all. What you can do is give the classes some kind of "conversion constructor" that takes an object of the respective other class and maps the fields to its own ones:
namespace NS1
{
public class Address
{
// fields go here
public Address(NS2.Address add2)
{
this.Name = add2.Name;
this.Street = add2.Street;
// etc.
}
}
}
Casting namespace is conceptually incorrect. It’s more appropriate to say casting from one type to another. Unless the two classes are related in terms of inheritance, you cannot use casting at all.
Is it possible to extend the SubSonic generator without modifying it's code?
I would like to add my own custom methods that i can use inside the templates. Somthing similair like the Utility.GetVariableType method.
You can't extend the built in templates, but you can replace them with your own templates without changing SubSonic.dll. See the templateDirectory parameter here: http://subsonicproject.com/docs/Generated_Classes/#Customizing_Active_Record
An example configuration would be:
<SubSonicService defaultProvider="Northwind" enableTrace="true"
templateDirectory="C:\Program Files\SubSonic\SubSonic 2.0.3\Templates\MVC">
<providers>
<clear/>
<add name="Northwind" type="SubSonic.SqlDataProvider, SubSonic"
connectionStringName="Northwind" generatedNamespace="Northwind"/>
</providers>
</SubSonicService>
You can get the current version of the built-in ActiveRecord templates from here.
I've found the solution for my own problem :).
I can now extend SubSonic with functionality i need in the templates without needing to rebuild or change any of the SubSonic code itself.
It works for what i wanted to do and i think it can be usefull for others as well so here it is:
Create a new class library SubSonicHelper. Mine has a class looking like this:
using System;
using System.Collections.Generic;
using System.Text;
namespace Helpers.SubSonic
{
public class GeneratorHelper
{
public bool IsColumnAllowed(string columnName)
{
return columnName.Length == 1 ||
(columnName.Length > 1 &&
(!(columnName[0].ToString().Equals("_") &&
columnName[columnName.Length - 1].ToString().Equals("_"))))
}
}
}
Build the assembly and copy SubSonicHelper.dll to your subsonic project.
Setup your SubSonic project to use your own templates using the templateDirectory parameter.
Edit your own templates and at the following after the const bool showGenerationInfo = false;
System.Reflection.Assembly a = System.Reflection.Assembly.LoadFile(
System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(), "SubSonicHelper.dll"));
object instance = a.CreateInstance("Helpers.SubSonic.GeneratorHelper");
Type type = instance.GetType();
After this you have an instance of the GeneratorHelper that you can use inside the template. For accessing the methods you need to do the following:
Create an array of objects for the parameters of the method you want to use. I have the columnName parameter which i set to col.propertyName. This is inside the foreach (TableSchema.TableColumn col in cols) loop in the Update method.
Call the method you want to use with the object array as argument.
Check the result object to see the result of the method.
object[] arg = new object[]{col.PropertyName};
object isColumnAllowedResult = type.InvokeMember("IsColumnAllowed", System.Reflection.BindingFlags.Default | System.Reflection.BindingFlags.InvokeMethod, null, instance, arg);
if (Convert.ToBoolean(isColumnAllowedResult))
That's it! Now i can extend the SubSonicHelper class with other methods i want to use inside the template.
The short answer is no. If you come up with something useful, submit a patch and it will likely be integrated into the core. You can submit patches here: http://code.google.com/p/subsonicproject/issues/list
can you not import a dll in the template?
like
<%# Import namespace="NewHelpers.Utilities"%>
and then call the function or create an instance of the object