Porting System.Configuration to .NET Core via POCOs? - c#

We've got a .NET Framework .dll that we're porting to .NET Core. Currently we're inheriting from ConfigurationElement and ConfigurationSection from System.Configuration to create custom configuration sections in the app.config (or it's .NET Core equivalent)
Questions:
It appears the .NET Core way is Microsoft.Extensions.Configuration. Is that correct? Because it lives on ASP.NET Core's github project instead of .NET Core's github project. We have no ASP parts.
If so, any .NET Core examples on creating and loading custom configuration sections not relying on startup.cs ? Ideally we'd like to read from a text source (XML or JSON) directly into a POCO object graph for strongly typed benefits.
With .NET Core 2.0, will there be any support for the traditional ConfigurationElement and ConfigurationSection negating the need for any such porting efforts to begin with ? Reason I ask is the .NET Core 2.0 Roadmap says
.NET Core gain over 5,000 APIs from .NET Framework as part of this work making it a broader platform.

I am not aware of app.config and System.Configuration support in .NET Core. Probably, no, but that's just a guess. You can setup configuration for .NET Core application in Main method:
class Program
{
static void Main(string[] args)
{
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
var poco = new Poco();
configuration.Bind(poco);
Console.WriteLine(poco);
Console.ReadKey();
}
}
class Poco
{
public bool Enabled { get; set; }
public Sort Sort { get; set; }
public override string ToString()
{
return $"Enabled={Enabled}, SortOrder={Sort.Order}";
}
}
class Sort
{
public int Order { get; set; }
}
appsettings.json is following:
{
"enabled": true,
"sort": {
"order": 2
}
}
Outputs:
Enabled=True, SortOrder=2
You need to reference Microsoft.Extensions.Configuration.Json and Microsoft.Extensions.Configuration.Binder packages.
No dependency on ASP.NET Core.
Microsoft.Extensions.Configuration is quite extensible, it can use different settings providers like environment variables, command line arguments, etc. So it is possible to implement custom provider for ConfigurationSection-like configuration if needed.
Based on this comment they are not going to bring System.Configuration to NetStandard 2.0.

With the dust settling down from .NET Standard 2.0 release it is possible to use your usual System.Configuration even in .NET Core 2.0 on Linux!
Here is a test example:
Created a .NET Standard 2.0 Library (say MyLib.dll)
Added the NuGet package System.Configuration.ConfigurationManager v4.4.0. This is needed since this package isn't covered by the meta-package NetStandard.Library v2.0.0
All your C# classes derived from ConfigurationSection or ConfigurationElement go into MyLib.dll. For example MyClass.cs derives from ConfigurationSection and MyAccount.cs derives from ConfigurationElement. Implementation details are outof scope here but Google is your friend
Create a .NET Core 2.0 app (e.g. a console app, MyApp.dll). .NET Core apps end with .dll rather than .exe in Framework.
Create an app.config in MyApp with your custom configuration sections. This should obviously match your class designs in #3 above. For example:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="myCustomConfig" type="MyNamespace.MyClass, MyLib" />
</configSections>
<myCustomConfig>
<myAccount id="007" />
</myCustomConfig>
</configuration>
That's it - you'll find that the app.config is parsed properly within MyApp and your existing code within MyLib works just fine. Don't forget to run dotnet restore if you switch platforms from Windows (dev) to Linux (test).

Besides described way of migration to Microsoft.Extensions.Configuration (which totally makes sense) as it should (at least I hope) be possible to use the same types from System.Configuration on .NET Core 2.
Here's System.Configuration types in corefx:
https://github.com/dotnet/corefx/tree/master/src/System.Configuration.ConfigurationManager
I can't tell you that they are fully compatible with the ones from full .NET. But at least it's something that takes us a hope )
So it looks like .NET Core 2 will have that old System.Configuration stuff but not netstandard2. Probably it's because MS doesn't want to share these types among other platforms (Xamarin).

Related

Configuration file .NET framework Library to .NET Core

I'm migrating a custom ORM library from .NET Framework 4.5 to .NET standard 2.0. I've configured the solution to be multitarget: .NET Framework 4.5.2 and .NET Core 2.2.
The biggest change is how to manage the Configuration files in .NET Core.
The library is made to refer always to the internal config file (that use ConfigurationManager) to retrieve all kind of configuration options, even the connectionstrings.
Here is an example on how this config class is structured
public static class MyConfig
{
public static string MyCnString
{
get
{
if (string.IsNullOrEmpty(_mycnstring))
_mycnstring=ConfigurationManager.ConnectionStrings["mycnstring"]
return _mycnstring;
}
}
public static string MySetting
{
get
{
if (string.IsNullOrEmpty(_myappsetting))
_myappsetting = ConfigurationManager.AppSettings["MyAppSetting"];
return _myappsetting;
}
}
}
This class is mainly used inside the library.
Now I would like to understand how to refactor this class to be .NET core compatible, and allow the library to be used in .NET Core app or Site.
I cannot figure how to use IConfiguration or IOption in a startup.cs to initilize the MYCOnfig class and then be used as a static class by the library as in .NET Framework.

Why WindowsIdentity class is not visible in .NET Core

Having the code below in VisualStudio 2017 .NET Core 2.0 Console App
using System;
using System.Security.Principal;
namespace smallTests
{
class Program
{
static void Main(string[] args)
{
var identity = WindowsIdentity.GetCurrent();
}
}
}
Why am I getting the error:
The name 'WindowsIdentity' does not exist in the current context
If I can see this class in .NET Core 2.0 library in .Net Core docs ?
Same code works in .NET Console app.
[EDIT]
#Will #JohnnyL Commented that I do not refer, System.Security.Principal.Windows.dll, that is true.
But I am curious why it is not working, because
in .NET 4.6.1 project (where class WindowsIdentity is visible) I also do not refer this System.Security.Principal.Windows.dll specifically. However i refer System.dll.
I always thought that it works like namespace hierarchy. For instance, when I refer to
System.Security.Principal.dll
i can use class which is in
System.Security.Principal.Windows.dll.
Am I wrong?
I added System.Security.Principal.dll to .NetCore solution by hand but it still does not work.
[EDIT2]
#Will Thank you a lot for expaining the subject it helped me a lot.
I tried to figure out is WindowsIdentity compatible with Core and it seems that it is please see:
in this apisof.net in Declarations area i can see that WindowsIdentity is in .Net Core 2.0 System.Security.Principal.Windows, Version=4.1.1.0, PublicKeyToken=b03f5f7f11d50a3a
but i do not have System.Security.Principal.Windows.dll in references, should I add it? If yes from where?
in .NET Core api reference i see this class in the list (what is the purpose of that listing if it is not compatible with core?
I also find information about that class in that link
Am I looking in wrong places?
Microsoft announced Windows Compatibility Pack for .NET Core a few weeks ago,
https://blogs.msdn.microsoft.com/dotnet/2017/11/16/announcing-the-windows-compatibility-pack-for-net-core/
And by analyzing the source code of System.Security.Principal.Windows.csproj and the commit adding it,
https://github.com/dotnet/corefx/blob/master/src/System.Security.Principal.Windows/src/System.Security.Principal.Windows.csproj
My conclusion is that this is also part of the Windows only compatibility libraries, so can only be used on Windows.
To add that to your project, open your csproj and add a PackageReference tag for System.Security.Principal.Windows manually (or use Visual Studio's NuGet Package Manager).

Referencing between NetStandard and .Net Framework

I'm trying to get .Net Framework and NetStandard assemblies to communicate with each other (to learn what is possible). I currently have four projects, two Framework 4.5.2 projects and two NetStandard1.2 projects:
Framework452.Library
NetStandard12.CentralLibrary
NetStandard12.BaseLibrary
Framework452.Tests
The referencing structure is:
Framework452.Tests references NetStandard12.CentralLibrary: working by adding the NetStandard.Library nuget package to Framework452.Tests.
NetStandard12.CentralLibrary references NetStandard12.BaseLibrary: working without modification.
NetStandard12.CentralLibrary references Framework452.Library: Not working, even when Framework452.Library has the NetStandard.Library nuget package installed.
Can NetStandard projects reference Framework projects? If so, what do I need to do to get them to communicate? At the moment I can add the reference, but it is not visible to the code.
Update
I recreated the solution and added the code below, which when I try to compile gives the following error from the Framework452.Tests project:
Error CS0006: Metadata file
'~\TryNETStandard\NetStandard12.CentralLibrary\bin\Debug\netstandard1.2\NetStandard12.CentralLibrary.dll'
could not be found.
namespace Framework452.Library
{
public class Returner452 {
public static bool ReturnTrue() { return true; }
}
}
using Xunit;
namespace Framework452.Tests
{
public class Class1 {
[Fact]
public void FrameworkTest() {
Assert.True(NetStandard12.CentralLibrary.Class1.Return452());
}
[Fact]
public void NetStandardTest() {
Assert.True(NetStandard12.CentralLibrary.Class1.Return12());
}
}
}
namespace NetStandard12.BaseLibrary
{
public class Returner12 {
public static bool ReturnTrue() { return true; }
}
}
using Framework452.Library;
using NetStandard12.BaseLibrary;
namespace NetStandard12.CentralLibrary
{
public class Class1
{
public static bool Return452() { return Returner452.ReturnTrue(); }
public static bool Return12() { return Returner12.ReturnTrue(); }
}
}
According to this page https://learn.microsoft.com/en-us/dotnet/standard/net-standard#net-platforms-support you should be able to achieve your purpose because .NET Standard 1.2 support .NET Framework 4.5.1 (UPDATE: This statement is not 100% correct. Please see the Update section below.)
I tried to set up a solution in VS 2017 and set the references as you described. Here is the result.
and this is the Class1.cs in NetStandard12.CentralLibrary
The code compiles fine without any errors.
Note: your code may fail if the Framework452.Library uses an API that is not supported by .NET Standard 1.2 (e.g Winforms, Win32 API or any Microsoft proprietary library that does not make sense for cross platform).
I recommend this youtube playlist on the .NET standard introduction from one of the MSFT https://www.youtube.com/watch?v=YI4MurjfMn8&list=PLRAdsfhKI4OWx321A_pr-7HhRNk7wOLLY
In .NET Standard - Checking Compatibilty , he recommended tools to help you find out what API is not supported in the .NET Standard.
Thing will become easier with .NET Standard 2.0 and 'compat shim'
UPDATE:
After trying again with more data provided by the question, it's true that a library targeting (depends) .NET Standard could not depend on a library that target .NET Framework. For some strange reason, the compiler allows me to compile the example that I gave above. This could be a bug in tooling.
After a little more research, I found a good example demonstrate the relationship between NetStandard and NetFramework: How .NET Standard relates to .NET Platform.
The graph here show the dependencies
According to the graph, there is no way a library that depends on .NET Standard could see/use the .NET framework implementation.
When .NET Standard 2 is released, this may change a little bit and you could reference .NET Framework via Compatibility Shim. See this video for more in-depth explanation https://youtu.be/vg6nR7hS2lI?list=PLRAdsfhKI4OWx321A_pr-7HhRNk7wOLLY&t=169
No, .NET Standard projects cannot reference framework projects.
.NET Standard projects need to be usable across platforms, forcing a dependency on the .NET framework by referencing an assembly targeting it makes this impossible.
Note that with some of the magic Microsoft is doing with .NET Standard 2.0 this is less true but the overall idea still stands.

Where should my application setting be in a .Net Core / EF Core class library project?

I am trying to store my database connection string in a config file so that I can change it depending on the deployment environment. My data access is using EF Core 1.1.0.
I have looked at some full .Net applications that use EF Core and use App.config to store and retrieve the connection string like this:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(ConfigurationManager.ConnectionStrings["AdventureWorks"].ConnectionString);
}
However, when I try that approach in my .Net Core class library project by creating the same App.config file, when I hit the above line of code I get an "Object reference not set to an instance of an object." exception.
So my question is.. Where should these settings be stored in a .Net Core class library project and how are they then retrieved? Should it be App.config, project.json, appsettings.json or some other file??
When i look at this :
Entity Framework Core 1.0 Connection Strings
I think he used Json. Said it was easier, and managed to answer himself. Make sure your files see each other and it should be ok. Sorry if it didn't help.

How to use Windows Runtime classes in .NET Core libraries?

I'm developing a library for use with WPF and Windows 10. I'm running into issues getting it to compile on the latter. Here is some of the code:
project.json
{
"frameworks": {
"net46": {
"frameworkAssemblies": {
"WindowsBase": "4.0.0.0"
}
},
"netcore50": {
"dependencies": {
"Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0"
}
}
}
}
Dependency.cs
using System;
using System.Collections.Generic;
#if NET46
using System.Windows; // .NET Framework 4.6
#elif NETCORE50
using Windows.UI.Xaml; // Windows 10 apps
#endif
public static class Dependency
{
public static DependencyProperty Register<T, TOwner>(string name, PropertyChangedCallback<T, TOwner> callback)
where TOwner : DependencyObject
{
// Code here....
}
}
While this compiles fine for net46 (which is the traditional .NET Framework), I'm having trouble getting it to work for netcore50 (which can be used by Windows 10 apps). For some reason, it looks like types like DependencyProperty or DependencyObject are not included in that configuration.
Is there a netcore50-compatible NuGet package I can install that contains these types, so I can use them from my library?
Thanks for helping.
EDIT: I just typed in DependencyProperty in VS and hit F12. It appears that the type lives in the Windows.Foundation.UniversalApiContract assembly, but there's no such package on NuGet.
Finally solved the problem on my own! (If you're looking for a quick answer, you may want to scroll down.)
I remembered by chance that the .NET Core GitHub repo had a bunch of WinRT-specific libraries, like System.Runtime.WindowsRuntime. So, I headed over there to see how they did it.
It appears they use some kind of internally-hosted "targeting pack", which contains a single Windows.winmd file (which holds all the types in the Windows Runtime), to achieve this affect. Unfortunately, the package is hosted on a private NuGet feed meant only for the .NET Core team, so I can't use it.
I've opened an issue about this on the CoreFX repo here, so I can petition Microsoft for an official solution to this problem. In the meantime, I've taken matters into my own hands. I've found all the different versions of Windows.winmd on my laptop, and uploaded them as NuGet packages. Here they are:
Target.Windows
Target.WindowsPhone
Target.WindowsRuntime
You can use them like this:
"frameworks": {
".NETPortable,Version=v4.5,Profile=Profile32": {
"dependencies": {
"Target.WindowsRuntime": "8.1.2"
}
}
}
After that, you'll be able to write something like this:
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
public class MyApp : Application
{
public MyApp()
{
var button = new Button();
button.Content = "Hello, world!";
}
}
and it'll just work.
With .NET Core 3 and up (now in preview) there is a package you can install that includes most WinRT classes Microsoft.Windows.SDK.Contracts
WPF Isn't compatible with .net Core nor are W10 Universal Apps, to my knowledge only Console apps and web apps are currently compatible with .net core, you should be able to still use the the new code base with the new project system but you will need to remove .net core from your configuration in order to compile
if you want to use .net core with linux with a desktop app you will simply have to wait, or use a compatible windowed app framework ( if any are available yet), you should be able to use a cross platform framework base around html/js such as Electron or Cordova ( not sure on this one on whether there is a desktop app framework with Cordova)

Categories