In monodroid or monotouch what should I use instead of app.config for configuration strings? - mono

I want to store development vs production connection strings and configuration strings in a monodroid project. I would normally store it as app settings in a web.config or an app.config, but how should I do it in monodroid and monotouch projects? I would also like for it to switch configurations automatically between debug and release builds just as visual studio does with *.config files. In an iOS app I could store these in a plist but I'd like a cross platform solution in mono.
How would I do this in monodroid or monotouch?

You should just use a static class with #if declarations.
Something like:
public static class Configuration {
#if DEBUG
public const string ConnectionString = "debug string";
#else
public const string ConnectionString = "release string";
#endif
}
The benefit to using app.config is the ability to change these settings on the file system without recompiling. On mobile, there isn't a good way (especially on iOS) to edit the file after it's deployed. So it's generally better to just use a static class and redeploy when you need to change the values. This will also work on all platforms, because it is just C# code doing the work.

there's a Xamarin centric AppSetting reader available at https://www.nuget.org/packages/PCLAppConfig
it is pretty useful for continuous delivery;
use as per below:
1) Add the nuget package reference to your pcl and platforms projects.
2) Add a app.config file on your PCL project, then as a linked file on all your platform projects. For android, make sure to set the build action to 'AndroidAsset', for UWP set the build action to 'Content'. Add you settings keys/values: <add key="config.text" value="hello from app.settings!" />
3) Initialize the ConfigurationManager.AppSettings on each of your platform project, just after the 'Xamarin.Forms.Forms.Init' statement, that's on AppDelegate in iOS, MainActivity.cs in Android, App in UWP/Windows 8.1/WP 8.1:
ConfigurationManager.Initialise(PCLAppConfig.FileSystemStream.PortableStream.Current);
3) Read your settings : ConfigurationManager.AppSettings["config.text"];

Related

C# CLR Excecption "BadImageFormatException: Could not load file or assembly"

I am using VS 2019 Version 16.8.2
I referred a "CLR Class Library(.NET Core)" project in my "WPF App (.NET)" project and i met a exception:
BadImageFormatException: Could not load file or assembly 'LibCLR, Version=1.0.7646.21580, Culture=neutral, PublicKeyToken=null'. An attempt was made to load a program with an incorrect format.
Let me first talk about how I did it.
Create a "WPF App (.NET)" project "TestCLR"
Add a new "CLR Class Library(.NET Core)" project "LibCLR" in this solution
The "common language runtime support" setting of "LibCLR"
Target "TestCLR" to ".NET 5.0"
"LibCLR.h" created automatically in project "LibCLR" and codes was inside
#pragma once
using namespace System;
namespace LibCLR {
public ref class Class1
{
// TODO: Add your methods for this class here.
};
}
Add "new LibCLR.Class1();" in MainWindow.xaml.cs in project "TestCLR"
using System.Windows;
namespace TestCLR {
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
new LibCLR.Class1();
}
}
}
Rebuild All and debug, then i met exception
Then i change the solution platform to x64 or x84, the exception were the same.
It works well if i choice "WPF App (.NET Framework)" for "TestCLR" in step 1 and "CLR Class Library(.NET Framework)" for "LibCLR" in step 2
Why did not it work?
Can not i use a "CLR Class Library(.NET)" project as a project reference in a "WPF App (.NET Core)" project?
How can i solve this problem?
You should change Platform target to "X86" here
The most common answer is changing between x86 and x64 targets. In a comment to your original question, here, you mentioned that you tried that and it didn't work for you. So, I have a suggestion. You are building a WPF project, and targeting dotnet 5.0. Dotnet 5.0 is OS-agnostic. WPF is OS-specific. It needs Windows.
Try using an OS-specific Target Framework Moniker. Open the .csproj file of both projects. Try setting both projects to <TargetFramework>net5.0-windows</TargetFramework>
Clean solution, rebuild, and test.
We've got a solution here that is dependent on Windows. We shouldn't have to, but let's try explicitly targeting it. Especially that C++ project.
More reading
NET 5: Merging .NET Core and .NET Standard with New Target Framework Monikers (TFMs)
New templates Targeting .NET 5.0
Cannot compile WPF applications targeting .NET 5

Unknown class in Compiled Swift Framework embedded in Objective-C Project

I have a framework binary built with Swift that I'm trying to incorporate into an Objective-C project. However the class in the framework isn't available.
In the swift framework, the class is defined like this:
#objcMembers
#objc public final class Messaging: NSObject, UINavigationControllerDelegate, LogsManagerDelegate {
...
}
I drag the archived and exported framework directly into the project to use and make sure the Defines Module is set to Yes in the Build Settings.
In the Objective-C I try to use the framework:
#import ContactAtOnceMessaging;
#implementation MessagingExperience
Messaging *messaging; // Unknown type name 'Messaging'
...
#end
If I drag the code for the framework directly into the project, Messaging is a known class so I know the Swift is okay.
I also tried changing the import to the following, but that didn't work.
#import "ContactAtOnceMessaging/ContactAtOnceMessaging-Swift.h"
I also tried using CocoaPods to import the framework and that hasn't helped.
What am I doing wrong?
I can confirm that I experienced the same problem as you. I was also able to resolve it. I'm not sure if the original problem was caused by an anomaly somewhere in my configuration. I did, however, test the following procedure and found it to work reliably with Xcode 9.3.
I first made a test Swift framework named Dynamic-Framework-Tester, in an Xcode project, and set it to be copied to an absolute path on every build.
I then performed the following steps to setup my Objective-C project:
Made a new project with Objective-C as the language.
Dragged the framework from its absolute path into the project without choosing "Copy items if needed".
Deleted the framework from Linked Frameworks and Libraries because it will get added automatically in step (4).
Added the framework to Embedded Binaries.
In build settings, set Always Embed Swift Standard Libraries to Yes.
Added my custom framework path to the Framework Search Paths setting in the build settings.
In the Objective-C project, I imported the framework using
#import Dynamic_Framework_Tester;
and called a method exposed in the framework from Objective-C.
Using a simulator, I was able to update the framework and have the changes applied on subsequent runs of the app.

Loading config file in Class Library

I have a Class Library, which is called by a VB6 client and VB.NET client. If the Class Library is called by the VB.NET client then there are settings in the app.config for Log4Net (http://logging.apache.org/log4net/). If the library is called by the VB6 code then there is no logging at the moment.
The question I have is about the app.config. If I have an app.config in the VB.NET client (Windows Forms) and the class library, then I assume that:
If client is Windows Forms then
Use VB.NET App.config
ElseIf client is VB6 then
Use Class Library app.config
Is that correct. I have done some research on MSDN, however I cannot find anything explicit and hence the question.
I don't think class libraries support app.config files directly - they merely use the app.config / web.config of the assembly that forms the process - so the console app, service, WinForms App etc.
app.config files are useful only to CLR executable assemblies and they are automatically loaded when the application runs.
If your executable is not a managed application (application developed using VB6 I assume), app.config is useless because CLR won't get loaded into the process (since it is not a managed app).
If your assembly is managed but not executable (class library), it is useless (useless in terms of execution, otherwise it can be used to copy the contents to an executable project's app.config).
Class library uses the config file of its host, so even if the class library project has a config file, it will not be reference at run time. Instead it will look for the config file of the host executing the DLL.
To avoid recompiling the code after the build to update a variable values like Development DB and Production DB, etc. You can either use setting or hard code a path in your program to look for a 'config' file. I use an XML file, with a key-value pair. I then load and read it to a list, or dictionary that i can use in my application like a 'config' file.
Now when I deploy, I can simply change the 'config' file in the hardcoded location in my dll to whatever environment without the need to rebuild the class library.

Creating MonoTouch binding with an Objective-C framework

I have a library in Objective-C that i want to bind to in monotouch (xamarin studio). This library is using a framework ('Firebase' framework), that I downloaded from a third party vendor. I compiled the library, and it built fine on XCode, and then created the .a files for i386 and armv7 architectures, and used lipo to generate my lib.a file. Now, I created a binding project, and added my .a file to it, which generated a .linkwith.cs file. However, when I used the binding project, it gave the following error:
"ld: framework not found Firebase"
My question is - How do I specify the Firebase framework? I tried this:
[assembly: LinkWith ("libtestfirebaseclient.a", LinkTarget.ArmV7 | LinkTarget.Simulator, ForceLoad = true, Frameworks = "CFNetwork Security Foundation Firebase")]
However, still the problem seems to be un-resolved. Can someone tell me how to create binding for a obj-c library that is depending upon a third party framework?
You probably do not need to reference Firebase as a platform, but instead (if it's not included in libtestfirebaseclient.a) add a new LinkWith attribute for it:
[assembly: LinkWith ("libtestfirebaseclient.a", LinkTarget.ArmV7 | LinkTarget.Simulator, ForceLoad = true, Frameworks = "CFNetwork Security Foundation")]
[assembly: LinkWith ("libfirebase.a", LinkTarget.ArmV7 | LinkTarget.Simulator, ForceLoad = true, Frameworks = "CFNetwork Security Foundation")]
I would suggest making sure that you have done all of the necessary process like like completing the ApiDefinition.cs file and defined all necessary enums and such in the StructsAndEnums.cs file. Also, I'm pretty sure you don't need to include Firebase in the LinkWith Frameworks section.
In my opinion, the best way to figure it out is to look at existing libraries that have been binded in the monotouch-bindings repository and see exactly how everything needs to be laid out. Download a library that has been bound, look at how each thing corresponds, and do the same for your project.
There is a detailed guide on binding Objective-C Libraries on Xamarin's website along with a Binding Types Reference Guide as a reference.

App.Config - client app or class library

I have experience using the Web.Config file in ASP.NET. I am trying to add an app.config file to a VB.NET project.
I am able to retrieve a connection string in one of the classes (in the class library) if I add the app.config to the client application, but I am unable to do so if I add the app.config to the Class Library project (I get a "object is not an instance" error). What is the difference between adding the app.config to the client app and adding it to the class library?
The app.config always belongs to the executable assembly. If a library tries to read the app.config, it will be actually reading the app.config that belongs to whichever executable is using that library. That is why you can put settings in your executable's app.config which apply to various .NET framework libraries.