Writing a library in a framework [duplicate] - c#

I'm writing a class library for a simple parser in C#. When I first created it, I used .NET standard 2.0, but now I need to migrate it to .NET 4.6 both to conform to the other projects in my solution and in order to use NUnit.
I tried to follow the instructions in the Microsoft documentation, but when I try to select another framework in the properties, I can only find other .NET standard versions.
How can I migrate it? Will I need to manually edit the .csproj file?

Open up the project file (.csproj) and change the TargetFramework to net462
<PropertyGroup>
<TargetFramework>net462</TargetFramework>
</PropertyGroup>

My personal experience in Visual Studio 2017 is that recreating project and adding existent sources is the simplest, safest and most effective way - because .Net Framework based csproj file has extra xml elements (comparing with Standard based), it seems changing "TargetFramework" is not enough.
Below is portion of diffs appeared by default:

If you are publishing your class library as a Nuget package then there is a better way to set this up. Check out this article:
https://weblog.west-wind.com/posts/2017/Jun/22/MultiTargeting-and-Porting-a-NET-Library-to-NET-Core-20
Basically you can setup your class library for multi targeting, allowing it to be imported into .net core projects as well as different versions of .net frameworks.

There are a few steps that I did and worked for me:
git push your code, so you have a back up :)
Unload the project in VS (right click on the project and unload)
Edit the project in VS (right click and edit)
Replace the TargetFramework OR/AND TargetFrameworkVersion with
<TargetFramework>netcoreapp2.0</TargetFramework>
Change the project line, that's usually the first line (after xml root) to:
<Project Sdk="Microsoft.NET.Sdk">
Remove the import that's usually the second line (after the xml root)
Keep your PropertyGroups that describe the build options, if you want (I want mine as are custom)
Remove the references and the file references, they are not needed.
Close the file and reload (right click reload).
Delete the assemblyinfo file (from properties folder) as it is not needed, the assembly version comes now from the proj
Right click on the project and go to properties to see that you don't have any error in proj file. Ensure that you don't have typos or tags that are not close.
Build. If you have dependencies that you are missing then right click and on the project and add them. - I suppose that you don't want to edit them in the proj. Or you can do a dotnet restore or dotnetbulid to add them, as you would like.
Hope this works for you. They seem a lot of steps but they are not that complicated, and this is one time effort.

Related

How can build independent dll's that depend on the same source?

I am building a few different C# libraries that both depend on a single C# file we'll call Dep.cs, and these dll's need to be used together in a Unity project. I'd like to set up these projects in the following way:
The C# libraries can be built independently of one another using Visual Studio
C# libraries (i.e. dll's) can be imported into a Unity project without conflicting symbols
The C# library projects (i.e. the source code for each library via git submodule for example) can be imported into a Unity project without conflicting sources.
I've solved (1) by including Dep.cs in each library project that requires it, though this causes issue with (2). And I've solved (3) by putting the dependency in a folder like Dependencies~ so that Unity ignores the file (this way no duplicate classes are found).
I'm having trouble solving (2) however. I thought I'd be able to add Dep.cs as reference in the VS solution but This doesn't seem to work. I've heard of Assembly References but I am not sure if they do what I need.
You can use "Add File as Link" from Visual Studio "Add Existing File" screen. It also works well with git submodule, just place Dep.cs anywhere in a parent folder or in the solution's root directory.
To get the same result you can also directly edit the .csproj file and add a compile instruction:
<ItemGroup>
<Compile Include="..\..\Path\To\YourFile.cs" Link="YourFile.cs" />
</ItemGroup>
This method solves all the issues you mentioned.
To solve my problem I decided to modify the external scripts to be internal this way both dll's can compile with that source and not conflict with one another. The rest of the setup in my question remained the same so this solved (2) for me without compromising (1) and (3).

Neither PackageIcon nor PackageIconUrl work in dotnet build

I'm using visual studio 2017. I have a project for which I would like to generate a nuget with an Icon.
If I use
...
<PackageIconUrl>http://blabla/icon.png</PackageIconUrl>
I get the following error :
error NU5048: The 'PackageIconUrl'/'iconUrl' element is deprecated. Consider using the
'PackageIcon'/'icon' element instead. Learn more at https://aka.ms/deprecateIconUrl
[D:\myproject.csproj]
Fine, So I change my project to be something like :
...
<PackageIcon>core.png</PackageIcon>
...
<Content Include="..\Shared\core.png" Link="core.png" Pack="true" PackagePath="\" >
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
When I build my project now (dotnet build Myproject.csproj) I don't get any compilation errors.
However, when I want to view the generate nupkg in "Nuget Package explorer". I get the error :
The element 'metadata' in namespace 'http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd'
has invalid child elment 'icon' in namespace 'http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd'.
List of possible elements expected : 'contentFiles, desription, licenseUrl, projectUrl, language,
releaseNotes, frameworkAssemblies, summary, iconUrl, packageTypes, dependencies, copyright,
developmentDependency, repositoru, tags, references, title, serviceable' in namespace
'http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd'.
(so it seems the generated embedded nuspec has a wrong xml namespace - I have no idea how I can make it generate the new namespace) This is a Catch-22.
So it seems the only option is to leave the icon out.
(I also have visual studio 2019 and recently installed the .net core 3.0.100 SDK)
The move from <iconUrl>/<PackageIconUrl> to <icon>/<PackageIcon> is fairly new. While nuget.org supports parsing packages which use <icon> rather than <iconUrl>, some other package servers don't yet.
It sounds like you're simply browsing a directory with the NuGet Package Explorer, so the cause is probably that this doesn't yet understand <icon>.
While <iconUrl> is deprecated, I've found that it still works on nuget.org, so you should be able to continue using it until the rest of the tooling catches up. Alternatively if you don't actually care about browsing packages stored in a local directory and just care about nuget.org, then you can start using <icon>.
You might even be able to use both - I haven't checked.
At least I think you can feel free to use the PackageIconUrl for now, as canton7 mentioned above, the move is fairly new. You can consider that as a kind reminder.
For the latest VS2019 release version 16.3.3, its project template still supports PackageIconUrl by default. For .net core and .net standard class library project, if we Right-click project=>Package tab we can see:
And it is equivalent to <PackageIconUrl>http://xxx/icon.png</PackageIconUrl> in xx.csproj, so I think you can just ignore that warning or use <NoWarn>NU5048</NoWarn>.
You need to make sure that the icon is part of the package. You can verify that it's in there by unzipping your nupkg file.
From a Microsoft site:
<PropertyGroup>
...
<PackageIcon>icon.png</PackageIcon>
...
</PropertyGroup>
<ItemGroup>
...
<None Include="images\icon.png" Pack="true" PackagePath="\"/>
...
</ItemGroup>
Also (from here):
PackageIconUrl is deprecated in favor of PackageIcon. However, for the best downlevel experience, you should specify PackageIconUrl in addition to PackageIcon.
There is also an example project with icon: https://github.com/NuGet/Samples/tree/main/PackageIconExample

How to remove .ncrunchproject files (or any other files that are similar) from .Net Core project/solution

I have added NCrunch to my .Net Core solution and now this file was added to all projects:
ProjectName.v3.ncrunchproject
I have added this to gitignore so it's not going to source control, but how can I remove it from Project?
There is an option of excluding this file explicitly in each and every project by either clicking Exclude in menu or adding it manually in .csproj file. I hope though that a better solution exists.
One way of solving this is to modify DefaultItemExcludes in sdk project props. For example go to:
C:\Program Files\dotnet\sdk\<version>\Sdks\Microsoft.NET.Sdk.Web.ProjectSystem\build\netstandard1.0
and modify Microsoft.NET.Sdk.Web.ProjectSystem.props.
Find something like:
<DefaultItemExcludes>$(DefaultItemExcludes);**\node_modules\**;node_modules\**</DefaultItemExcludes>
and change it to:
<DefaultItemExcludes>$(DefaultItemExcludes);**\node_modules\**;node_modules\**;**\*.ncrunchproject</DefaultItemExcludes>
After Visual Studio restart it should be automatically excluded from your project. This is not a perfect solution, because you will have to do it for every project type and sdk you have.

Adding OutDir property to all solution projects

I want TFS to build my projects into separate folders in Binaries folder. I have found the solution: http://blog.stangroome.com/2012/02/03/override-the-tfs-team-build-outdir-propert (I have to use .Net 4.0). However, I have mane projects in the solution and new projects may be developed by other developers, so I wouldn't like to change every *.csproj file by adding
<OutDir Condition=" '$(PreferredOutDir)' != '' ">$(PreferredOutDir)$(MSBuildProjectName)\</OutDir>
How could I add this line for every project automatically, for example in before.Foo.sln.targets?
You'll need to touch each one of your projects if you want an architectural solution that allows you to change this property globally from a single location.
Make a separate XML script file called "Common.targets" that is included as an and referenced by each of your projects after the first .
In each of your .csproj files, remove the property and add a after the first PropertyGroup, but make sure does not exist after this import.

C# - Code compiler for .NET & CF.NET

I've a same project that need to be compiled with .NET and Compact .NET Framework.
It is possible to create a C#
compiler that will compile my
project with both framework ?
Some feature aren't present in
CF.NET Framework so I created it by
myself (creating classes having
exactly the same name & options that
in .NET Framework. If I decore this
classes with an attribute like
[CF35] it's possible to parse the
project and :
Use this class when compile the
project using CF.NET
Ignore this class when compile the project using
.NET
?
Thanks for all constructive answers.
[EDIT]
I know the solution that consists to create two projects referencing the same files.
Problem is, you should every time compile both manually.
Moreover, when you add a file to one, you need to open the second and reference it too, that it's just borring to do and according that we are many people to work on the same project, I would like to do this part automatically.
Seems to be possible?
[EDIT 2]
All works fine except ... resources files !
So, to resume, I've three project :
the development project (CF.NET)
the release project (CF.NET 3.5), including all files via ""
the release project (NET 3.5), including all files via ""
As said, all works fine, but now my problem is using Resources files.
What's the method to apply to use it?
When I use the development project, Resource file is correctly retrieved
When I use the two other projects, ResourceManager throws MissingManifestResourceException
Any idea?
You'll need to create different build configurations for each and define a custom flag like USE_CF. Then wrap your custom classes with #if USE_CF and #endif so they get ignored when compiling without that flag
The basic idea would be to decorate your code with #if compiler directives for each framework version?
#if CFNET
// .net CF code
#else
// .net code
#endif
From here one you have two options:
A) 1 project file with custom build configurations
If you would like to have everything in 1 csproj file you'll need to modify it manually. Since this is a msbuild file this is more of a msbuild problem. I figure you would need to do the following things:
Use 2 platform names say "NET" and "CF" (instead of the default Any CPU or x86)
Define CF constant (From now on Edit csproj):
<PropertyGroup Condition="'$(Platform)' == 'CF'">
<DefineConstants>CF</DefineConstants>
</PropertyGroup>
Import correct build targets depending on selected platform:
<Import Condition="'$(Platform)' == 'NET'" Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Condition="'$(Platform)' == 'CF'" Project="$(MSBuildToolsPath)\<CFtargets>.targets" />
I don't know the targets file name of CF since I don't have it installed. It sould be somewhere in C:\Windows\Microsoft.NET\**.targets
B) 2 project files each containing the appropriate build configuration
As I initially pointed out, and also some commenter pointed out, the best solution is to have 2 project files, that you keep in sync. You can have the same source files in both project files.
So an idea would be (instead of copying the file list manually each time) to
think about using T4 templates, to keep the source files in sync (and have 2 solutions, so you wouldn't be prompted to reload the whole solution each time) or to
modify the two csproj files and use a wildcard compile tag like this:
<Compile Include="**/*.cs"/>
There's only one C# compiler, it emits the exact same IL for whatever platform. What's different are the reference assemblies, you have to use the CF versions for the project that targets CF, the desktop versions for the project that targets .NET. Which requires two projects. They can reference the same source code files. Adding CF-only source code files is now of course no longer a problem.
Keeping projects in sync is a feature available in VS2010. Intended for Silverlight, pointless for a CF project of course since it no longer supports it.
a better way is to create your normal project class library (.NET) and add all of your code. Then create your second class library project (.NET CF) but reference the code files from the first project (not copy, but reference). Then you end up with 2 DLL's and you don't have to deal with nasty ugly compiler directives. You get the result you want with no extra work to maintain both projects. Obvisouly you would need to be careful with what you put in the code since .NET CF is limited compared to .NET. I don't know how to add file references (shortcuts) using visual studio but I open the proj file in notepad and use relative paths to the files to include. I've used this method for .NET/.NET CF and also .NET/Silverlight
Also, have a look at Portable Library Tool CTP http://visualstudiogallery.msdn.microsoft.com/b0e0b5e9-e138-410b-ad10-00cb3caf4981/?localeName=ko-kr

Categories

Resources