I encountered this confusing names-resolution problem while trying to convert legacy solution with .NET 4.6.1 projects to the new SDK-style project formats. I was able to create a minimal repro solution LegacyVsSdkStyleProjectNameResolution, which is on GitHub here:
https://github.com/PaloMraz/LegacyVsSdkStyleProjectNameResolution.git
The solution contains:
3 legacy projects targeting .NET Framework 4.6.1 residing in the „Legacy“ solution folder; the project names start with „Legacy.“).
3 SDK-style projects targeting .NET residing in the „Sdk“ solution folder; the project names start with „Sdk.“.
(Please forgive me the non-intuitive assembly / namespace / class names – I could not use the original names and was not able to devise something more feasible).
The dependencies are shown in this image:
The problem is, the Legacy.Common.Configuration project successfuly compiles with this Bundle class declaration:
using Legacy.Common.Data;
namespace Legacy.Common.Configuration
{
public class Bundle
{
public Person Person { get; set; }
}
}
But the Sdk.Common.Configuration produces compilation error CS0118 ('Person' is a namespace but is used like a type):
using Sdk.Common.Data;
namespace Sdk.Common.Configuration
{
public class Bundle
{
public Person Person { get; set; }
}
}
Can anybody please explain, why the C# compiler in the Sdk.Common.Configuration project resolves the Person type symbol incorrectly to namespace Sdk.Common.Person, but in the Legacy.Common.Configuration it resolves it correctly to Legacy.Common.Data.Person class?
In SDK-style projects, a project will automatically inherit all of the things that its dependencies depend on. In legacy projects this had to be done manually, with the tooling inserting explicit references to all of the things that a new dependency depended on.
So in your SDK-style project, Sdk.Common.Configuration is inheriting a reference to Sdk.Common.Person.Management, by virtue of the fact that it references Sdk.Common.Data.
Sdk.Common.Person.Management defines the namespace Sdk.Common.Person:
namespace Sdk.Common.Person.Management
{
...
}
While Sdk.Common.Data defines the class Sdk.Common.Data.Person.:
namespace Sdk.Common.Data
{
public class Person
{
}
}
Sdk.Common.Configuration then does this:
using Sdk.Common.Data;
namespace Sdk.Common.Configuration
{
public class Bundle
{
public Person Person { get; set; }
}
}
There, the compiler searches the namespace Sdk.Common.Configuration (and Sdk.Common, and Sdk) for Person before it considers that using. It finds Sdk.Common.Person which is a namespace, and complains because you're using a namespace as a type.
If you include the using inside the namespace, this order flips, and the compiler will search Sdk.Common.Data first, and find the Sdk.Common.Data.Person class:
namespace Sdk.Common.Configuration
{
using Sdk.Common.Data;
public class Bundle
{
public Person Person { get; set; }
}
}
See this answer for details.
As for how to solve this, first off don't define a class and a namespace with the same name. If you can't avoid this, you can either change the location of the using as shown above, or use the fully-qualified name of the Person class.
If you want to mirror the legacy behaviour of Sdk.Common.Data's references not being inherited by Sdk.Common.Configuration, use PrivateAsserts="All" on the ProjectReference which includes Sdk.Common.Person.Management.
<ProjectReference Include="..\Sdk.Common.Person.Management\Sdk.Common.Person.Management.csproj" PrivateAssets="All" />
This states that Sdk.Common.Person.Management is a private dependency, which isn't inherited by anything which references Sdk.Common.Data.
Related
In my net5 project I have .cs file with IgnoresAccessChecksToAttribute
[assembly: IgnoresAccessChecksTo("MyOtherProject")]
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
public sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
AssemblyName = assemblyName;
}
public string AssemblyName { get; }
}
}
Also in my solution there is "MyOtherProject", which has some internal types. It is referenced via ProjectReference:
<ProjectReference Include="..\..\src\MyOtherProject\MyOtherProject.csproj" />
When I try to use one of these internal types I am getting error
'Type' is inaccessible due to its protection level
Am I doing something wrong?
The IgnoresAccessChecksToAttribute is supported by the runtime, but not by the compiler. It is mainly intended to be used by dynamically generated code where no compiler support is needed.
There was a pull request to get it in the compiler but the Roslyn team rejected it, see https://github.com/dotnet/roslyn/pull/20870.
One possible way to do this is with the https://www.nuget.org/packages/IgnoresAccessChecksToGenerator package. That package will create reference assemblies for you so that the compiler is happy.
But since you want to use internal types from your own project, why don't you go the supported way of the InternalsVisibleToAttribute? The IgnoresAccessChecksToAttribute is only needed if you can't change the code of the assembly containing the internal type.
I created a new Razor Class Library (using "dotnet new razorclasslib"). I then created a folder called Models in the new library and it contains a class with the following test code:
using System;
namespace TestLibrary.Models
{
public class TestModel
{
public string TestMethod { get; set; }
}
}
However, when I try to use this class from the web application project (by referring to it as TestLibrary.Models.TestModel) I keep being told that the TestLibrary.Models namespace doesn't exist. The exact error is:
The type or namespace name 'Models' does not exist in the namespace 'TestLibrary' (are you missing an assembly reference?) [TestApplication]
I'm assuming I'm missing something simple, just can't figure out what.
This issue was somehow related to the issue posted here: Razor Class Library MSBuild MSB4062 Error During Compile. Once that was resolved this issue went away.
I'm not familiar with namespaces and can't make it to work in visual studio 2017 community.
I created a solution with a empty project, I added a class file in that project:
namespace MainProject
{
class MainClass
{
//some methods
}
}
then I added a empty project to the solution and also added a class file:
namespace MainProject.SubProject
{
class SubClass
{
MainClass var;
public SubClass()
{
var=new MainClass();
}
}
}
The solution structure is like that:
Solution
|
|__MainProject
| |__MainClass.cs
|
|__SubProject
|__SubClass.cs
But I receive the error: error CS0246: The type or namespace name 'MainClass' could not be found
I don't understand what I'm missing.
You seem to have two problems (unless you've glossed over referencing MainProject from SubProject).
1) Classes are internal by default. For it to be seen by another project, it either needs to be intentionally exposed to that other project or, more commonly, marked as public:
public class MainClass
{
//some methods
}
2) You haven't added a reference to your MainProject project from SubProject, so even if you fix #1, you'll still have a problem.
You can add a reference by right-clicking the SubProject in Solution Explorer, selecting References (or Dependencies if you're working with .NET Core/Standard), selecting Add Reference, and then selecting your MainProject from the Projects list.
I have the following object in a class library:
namespace ID.CentralisedObjects
{
public class Details
{
public string ContactName { get; set; }
}
}
in the aspx page in my website project (which has a reference to the class library), I am trying to print out the ContactName by using code along the lines of
<div><%= ID.CentralisedObjects.Details.ContactName %></div>
However, it is thinking that the ID at the start of this is Page.ID so it isn't finding my object properly. How do I make it look for the class library ID?
standard naming of namespace has enough influence on your application, changing it according to the naming namespaces guidelines will solve your problem
http://msdn.microsoft.com/en-us/library/893ke618(v=vs.71).aspx
For the namespace conflict: use a qualifier
using DrawCharts IDS = ID;
IDS.CentralisedObjects.Details.ContactName
The other mentioned problems are unresolved by this solution.
Using .NET 2.0, C#, Windows Forms development, Enterprise Library 3.1.
We have a project namespace (call it Project). We also have several sub-namespaces inside of that project, for example Project.Namespace1, Project.Namespace2, etc.
In one class, we define enums and such to be used with the Enterprise Library Logging block, like this:
namespace Project.Logging
{
public static class Logging
{
public enum LogPriority
{
// enum values here
}
}
}
In another class, I use the enum values so I need to declare a using statement. Same project, so there is no assembly to reference, right?
If I declare the using inside of the local namespace, like this, it works fine:
namespace Project.SomeName
{
using Project.Logging;
// code referencing the Logging enum
}
However, if I put the using statement outside of the local namespace declaration, I get the "type or namespace name 'LogPriority' does not exist in the namespace 'Project.Logging'... Like this:
using Project.Logging;
namespace Project.SomeName
{
// code referencing the Logging.LogPriority.whatever
}
Why is this? Has anyone run across this before?
I have run into similar (though not exactly the same) problems before when using a class that has the same name as its namespace.
Oddly enough it seemed to compile ok on some developers pc's but not on others. In the end we made sure that no namespace contained a class of the same name.
namespace Project.Logging
{
public static class Logging // this is what caused the probems for me
{
}
}
I also had a wired error. I cannot find any namespace which is coming from different assemblies, but begins with executing assembly name.
Finally, I found out that I have set the target framework to .NET framework client profile.
Yes, most likely you have an unusual value set for the "Default Namespace" in your project properties. I would validate the project configuration.
We ran into this issue before and it all went down to ambiguous naming of the namespace and the class name.
When we tried to have our namespace as Services.Web.xxx and also add in a service reference as Services.Web.xxxx and ALSO add a references to an assembly that was named Services.Web.xxx you can only imagine the problems we ran into.
In the end to fix it we simply did a rename to make sure that there was only one instance of the Services prefix
Also you could do the following and create an alias to LogPriority to LogEnum:
using LogEnum= Project.Logging.Logging.LogPriority;
namespace Project.SomeName
{
internal class MyClass
{
public MyClass()
{
LogEnum enum1 = LogEnum.None;
}
}
}
namespace Project.Logging
{
public static class Logging
{
public enum LogPriority
{
None,
Default
}
}
}
It definitely can make a difference if you have usings inside or outside the namespace. There is a good discussion here, and it is likely to be related to your default namespace settings.