I recently recognized that I can use the C# 10 feature file-scoped namespaces in .NET Standard 2.0 projects as well by setting <LangVersion>10</LangVersion> in the csproj file.
However, global usings don't work that way, I'm getting compiler errors due to missing using statements.
Are there any tweaks so that I can use global usings in a .NET Standard 2.0 library as well?
I'm not sure why it doesn't work with a separated .cs file. However, a workaround that works is using the MSBuild syntax. In your .csproj you can add the following:
<ItemGroup>
<Using Include="System.Linq" />
</ItemGroup>
There are some keywords you can use - like Alias or Static -, as you would do in a normal .cs file.
<ItemGroup>
<Using Include="Test.Namespace" Alias="Domain" />
</ItemGroup>
And then in your code, you can do the following:
namespace Test.Namespace
{
public class TestClass {}
}
namespace Another.Namespace
{
new Domain.TestClass();
}
If it helps, I found this information in the following blog post.
Related
I have a Visual Studio 2022 solution, with multiple projects, but four in particular are interesting here.
Provider1 which is based on .NET Framework 4.
Provider2 which is based on .NET 6.
Provider1Test which is based on .NET Framework 4.
Provider2Test which is based on .NET 6.
The Provider1 project has a number of classes, all in the Provider.Data namespace, one of them being Class1. This is my source code. The Provider1.csproj file:
<ItemGroup>
<Compile Include="Class1.cs">
<SubType>Code</SubType>
</Compile>
...
</ItemGroup>
The Class1.cs file:
namespace Provider.Data
{
public class Class1
{
...
}
}
The Provider2 project has links to these source files, i.e. "Add"->"Existing item"->"As link". It compiles with different conditional compilation symbols, so the output is not the same as for the Provider1 project.
The Provider2.csproj file:
<ItemGroup>
<Compile Include="..\Provider1\Class1.cs" Link="Class1.cs" />
</ItemGroup>
The Provider1Test project is an NUnit test project, that tests Provider1. It has multiple test classes, one of them is TestClass1.
The Provider2Test project is also a NUnit test project, with a ProjectReference to Provider2. It links to the test classes in Provider1Test in the same way as the source code does. The Provider2Test.csproj file:
<ItemGroup>
<ProjectReference Include="..\Provider2\Provider2.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Provider1Test\TestClass1.cs" Link="TestClass1.cs" />
</ItemGroup>
The TestClass1.cs file:
using Provider.Data;
namespace ProviderTests
{
public class TestClass1
{
...
}
}
Now, this builds and runs just fine inside Visual Studio, but if I navigate to the Provider2Test folder and try to build with the dotnet build command, it doesn't find the source code.
C:\dev\DataProvider\Provider2Test>dotnet build
MSBuild version 17.3.1+2badb37d1 for .NET
Determining projects to restore...
All projects are up-to-date for restore.
Provider2 -> C:\dev\DataProvider\Provider2\bin\x64\Debug\net6.0\Provider.Data.dll
1 file(s) copied.
C:\dev\DataProvider\Provider1Test\TestClass1.cs(14,7): error CS0246: The type or namespace name 'Provider' could not be found (are you missing a using directive or an assembly reference?) [C:\dev\DataProvider\Provider2Test\Provider2Test.csproj]
Build FAILED.
What is the issue here, why doesn't dotnet build follow the reference path here, and how do I solve it?
I tried to create a TestClass2.cs file directly in Provider2Test, that is not a link but a standard compile include, and also using the Provider.Data namespace. It produces the same error.
I found a workaround, so I'm posting it here and I'm going with it for now, but I don't think it's a good solution, and it doesn't explain the original issue, so I'm not going to mark this as the accepted answer.
In Provider2.csproj, I added that if it is built with dotnet build, it has a post-build event that copies its source code dll to Provider2Test. This is not run if the project is build within Visual Studio ("$(MSBuildRuntimeType)" == "Full").
if "$(MSBuildRuntimeType)" == "Core" XCOPY "$(OutDir)Provider.Data.dll" "$(ProjectDir)..\Provider2Test\$(OutDir)" /Y /F
In Provider2Test.csproj I added a conditional assembly reference.
<ItemGroup>
<Reference Include="Provider.Data" Condition="$(MSBuildRuntimeType) == 'Core'">
<HintPath>$(OutDir)Provider.Data.dll</HintPath>
</Reference>
</ItemGroup>
I kept the ProjectReference in all cases (both "Full" and "Core"), in order to trigger a Provider2 build whenever Provider2Test is built.
I'm trying to figure out if I should start using more of internal access modifier.
I know that if we use internal and set the assembly variable InternalsVisibleTo, we can test functions that we don't want to declare public from the testing project.
This makes me think that I should just always use internal because at least each project (should?) have its own testing project.
Why shouldn't one do this? When should one use private?
Internal classes need to be tested and there is an assembly attribute:
using System.Runtime.CompilerServices;
[assembly:InternalsVisibleTo("MyTests")]
Add this to the project info file, e.g. Properties\AssemblyInfo.cs, for the project under test. In this case "MyTests" is the test project.
Adding to Eric's answer, you can also configure this in the csproj file:
<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>MyTests</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
Or if you have one test project per project to be tested, you could do something like this in your Directory.Build.props file:
<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>$(MSBuildProjectName).Test</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
See: https://stackoverflow.com/a/49978185/1678053
Example: https://github.com/gldraphael/evlog/blob/master/Directory.Build.props#L5-L12
If you want to test private methods, have a look at PrivateObject and PrivateType in the Microsoft.VisualStudio.TestTools.UnitTesting namespace. They offer easy to use wrappers around the necessary reflection code.
Docs:
PrivateType, PrivateObject
For VS2017 & 2019, you can find these by downloading the MSTest.TestFramework nuget
starting from .Net 5, you can use also this syntax in the csproj of the project being tested:
<ItemGroup>
<InternalsVisibleTo Include="MyProject.Tests" />
</ItemGroup>
I'm using .NET Core 3.1.101 and the .csproj additions that worked for me were:
<PropertyGroup>
<!-- Explicitly generate Assembly Info -->
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
</PropertyGroup>
<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
<_Parameter1>MyProject.Tests</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
You can use private as well and you can call private methods with reflection. If you're using Visual Studio Team Suite it has some nice functionality that will generate a proxy to call your private methods for you. Here's a code project article that demonstrates how you can do the work yourself to unit test private and protected methods:
http://www.codeproject.com/KB/cs/testnonpublicmembers.aspx
In terms of which access modifier you should use, my general rule of thumb is start with private and escalate as needed. That way you will expose as little of the internal details of your class as are truly needed and it helps keep the implementation details hidden, as they should be.
Keep using private by default. If a member shouldn't be exposed beyond that type, it shouldn't be exposed beyond that type, even to within the same project. This keeps things safer and tidier - when you're using the object, it's clearer which methods you're meant to be able to use.
Having said that, I think it's reasonable to make naturally-private methods internal for test purposes sometimes. I prefer that to using reflection, which is refactoring-unfriendly.
One thing to consider might be a "ForTest" suffix:
internal void DoThisForTest(string name)
{
DoThis(name);
}
private void DoThis(string name)
{
// Real implementation
}
Then when you're using the class within the same project, it's obvious (now and in the future) that you shouldn't really be using this method - it's only there for test purposes. This is a bit hacky, and not something I do myself, but it's at least worth consideration.
For .NET core you can add the attribute to the namespace as
[assembly: InternalsVisibleTo("MyUnitTestsAssemblyName")].
e.g. Something like
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Applications.ExampleApp.Tests")]
namespace Applications.ExampleApp
internal sealed class ASampleClass : IDisposable
{
private const string ApiVersionPath = #"api/v1/";
......
......
......
}
}
In .NET Core 2.2, add this line to your Program.cs:
using ...
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("MyAssembly.Unit.Tests")]
namespace
{
...
Add InternalsVisibleTo.cs file to project's root folder where .csproj file present.
Content of InternalsVisibleTo.cs should be following
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("AssemblyName.WhichNeedAccess.Example.UnitTests")]
I have a c# program that uses BouncyCastle. If I insert a reference to iTextSharp, the compiler generates many errors of classes already existing in both references. I have specified all the namespaces but it does not change anything.
Example:
Org.BouncyCastle.X509.X509Certificate certCopy = DotNetUtilities.FromX509Certificate(oCertificato);
How can I use BouncyCastle and iTextSharp together?
Just like #franco-de-giorgi said. Add an Alias to the library.
I'm just writing a full answer because I had to learn what is an Alias and how to add and Alias
Go to your references and go to properties on BouncyCastle, then change global to your personal Alias:
Then in your class use an external alias to your references like this (instead of using)
//using Org.BouncyCastle.Crypto.Parameters;
extern alias Merged;
In your classes add your alias
new Merged::Org.BouncyCastle.OpenSsl.PemReader
TL;DR: Use the PackageReference's Aliases attribute in *.csproj and add the alias to the affected *.cs files:
<PackageReference Include="PackageAffectedByConflict" Aliases="AltGlobalNamespace" />
extern alias AltGlobalNamespace;
using AltGlobalNamespace.ConflictedName;
According to the NuGet documentation from Microsoft:
In some rare instances different packages will contain classes in the same namespace. Starting with NuGet 5.7 & Visual Studio 2019 Update 7, equivalent to ProjectReference, PackageReference supports Aliases. By default no aliases are provided. When an alias is specified, all assemblies coming from the annotated package with need to be referenced with an alias.
The documentation also links an example on GitHub showing how to use the Aliases attribute:
PackageReferenceAliasesExample.csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NuGet.Versioning" Version="5.8.0" Aliases="ExampleAlias" />
</ItemGroup>
</Project>
Program.cs:
extern alias ExampleAlias;
using System;
namespace PackageReferenceAliasesExample
{
class Program
{
static void Main(string[] args)
{
var version = ExampleAlias.NuGet.Versioning.NuGetVersion.Parse("5.0.0");
Console.WriteLine($"Version : {version}");
}
}
}
I have Referenced MySql.Data on one project and Other project referenced nuget package which also referenced MySqlConnector inside of it. projects has dependency .
when i compile application im getting this error
This is application hierarchy
is there any way to avoid this? or did i do anything wrong when referencing packages?
Thanks
UPDATE
this is the same namespaces from difference libs
UPDATE 2
This is the sample repo which reproduced same issue
In NET.Framework projects you can go to the reference properties and set an alias for assembly. Net core projects doesn't fully support yet aliases for assemblies. But there is a workaround to use aliases in .net core. Edit your csproj file like this:
<Project Sdk="Microsoft.NET.Sdk.Web">
...
<Target Name="ChangeAliasesOfStrongNameAssemblies" BeforeTargets="FindReferenceAssembliesForReferences;ResolveReferences">
<ItemGroup>
<ReferencePath Condition="'%(FileName)' == 'MySqlConnector'">
<Aliases>MySqlConnectorAlias</Aliases>
</ReferencePath>
</ItemGroup>
</Target>
...
</Project>
then in your cs file before all usings:
extern alias MySqlConnectorAlias;
then you can reference to you type from MySqlConnector like this:
MySqlConnectorAlias::MySql.Data.MySqlClient.MySqlConnection
It will work If you remove mysql.data reference from Your project/references.
Hope it will work for you. for me it was worked. My project is ASP.NET Core Framework. Created project in VS2017 and opening in VS2019 at that time it introduced.
I am looking to retrieve the application version (essentially the <ReleaseVersion> property in the solution file) at runtime. How does one access this via code?
The standard way of setting the application version in .NET (and therefore presumably MONO) is to use the AssemblyVersion attribute. This is normally specified in the AssemblyInfo.cs file, but can be specified in other files, as is shown below.
To get the version at runtime, you can use the AssemblyName.Version property. The following is a slightly modified version of the code from the given link:
using System;
using System.Reflection;
[assembly:AssemblyVersion("1.1.0.0")]
class Example
{
static void Main()
{
Console.WriteLine("The version of the currently executing assembly is: {0}",
Assembly.GetExecutingAssembly().GetName().Version);
}
}
When compiled and run, it produces this:
The version of the currently executing assembly is: 1.1.0.0
The above was tested on both .NET (Visual Studio 2010), and Mono 3.0 (compiled using mcs from the command line, not Mono Develop).
have you tried using the suggestions in this forum --> get current version
It's an ugly hack, but you can utilise the BeforeBuild target to write that property to a file, which you then promptly include as an embedded resource. In your *.csproj file:
<ItemGroup>
<EmbeddedResource Include="release-version.txt" />
</ItemGroup>
<!-- .... -->
<Target Name="BeforeBuild">
<Exec WorkingDirectory="$(ProjectDir)" Command="echo $(ReleaseVersion) >release-version.txt" />
</Target>
....then in your C♯ code, you could create a property like this:
public static string Version {
get {
using (StreamReader resourceReader = new StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream("SBRL.GlidingSquirrel.release-version.txt")))
{
return resourceReader.ReadToEnd().Trim();
}
}
}
This should work on all major operating systems. Don't forget:
To add using System.Reflection; to the top of your file if you haven't already
To add the release-version.txt file to your version control's ignore list (e.g. .gitignore, etc.)