Preventing mobile projects from using certain .cs files in a Shared Project - c#

I am making a mobile app. In my Solution I have a shared project. Some of the files I do not want to be used in my iOS or Android builds.
My code looks something like this:
#if __MOBILE__
#else
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using Azure.Storage.Queues;
using Azure.Storage.Queues.Models;
using System;
namespace Blah.Utils
{
public static class AzureBlobService
{
public static async Task<string> CreateCloudQueue(string connectionString, string queueName)
{
// blah
}
}
}
#endif
This doesn't seem to be removing this file for my mobile apps. It still wants me to get those
nuget Azure.Storage packages. How can I get that #if to work the way I want it to?

Well after struggling with this for a long time and thinking it must be some obscure setting somewhere...it was because my shared library was being referenced by a project in between my mobile app project.
So in other words the projects were referencing each other like this:
Sharedproject <--- CoreLib proj <--- Mobile app proj
And I wasn't putting MOBILE in the 'Conditional Compilation Symbol' in the CoreLib proj properties.
ugh

Related

TypeLoadException when creating a custom renderer

I have an Android app created in Xamarin.Forms (4.7.0) and I want to implement ads from AdMob into it. For that i have to create a ViewRenderer wrapper around a View class that I made earlier. As soon as i add this line into the ViewRenderer
[assembly: ExportRenderer(typeof(AdBanner), typeof(AdBanner_Droid))]
then build and launch the app, I get this error :
System.TypeLoadException: 'Could not load type DDKTCKE.Controls.AdBanner, APP_NAME, Version=1.2.2.0, Culture=neutral, PublicKeyToken=null while decoding custom attribute: (null)'
I already tried :
Deleteing bin and obj folders
Wiping data from test device
Cleaning the solution
A also used the exact same code in a new blank project and it worked as it should. What could be causing problems in my main project ? What should I look into ?
To implement the Android renderer, two classes are needed; an AdBanner class in the Forms project (or an Netstandard project as a project reference to the Forms project) and an AdBannerRenderer in an Android project:
AdBanner:
using Xamarin.Forms;
namespace MyProject
{
public class AdBanner: View
...
AdBannerRenderer:
using Android.Gms.Ads;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using AdBanner = MyProject.AdBanner;
[assembly: ExportRenderer(typeof(AdBanner), typeof(Droid.Renderers.AdBannerRenderer))]
namespace Droid.Renderers
{
public class AdBannerRenderer : ViewRenderer<AdBanner, AdView>
...
I created a new project and copied all my code from my old solution into it. Now everything works flawlessly.
So once again this was a problem with VS that just popped up for no good reason and took me a week to find a f̶i̶x̶ workaround. And people wonder how anyone could hate Visual Studio.

My NuGet package doesn't seem to update in projects that use it as a dependency

Forgive what must be a very simple oversight on my part but I simply cannot get this to work as expected.
I am building a .NET Framework 4.6 Class Library that needs to be downloaded by other applications from a private nuget repository. Here is my process:
I have a test project, ConsoleApp5. It has a simple main function in it.
I download my NuGet package, MyPackage (right click on project and click Manage NuGet Packages, select appropriate repo and package, click install.)
I run my test. In this case, I'm simply trying to instantiate a class, something not difficult. I'm getting an error about class accessibility.
Back in MyPackage, I replace all instances of the word protected with public. I add a new class as well by right-clicking on the project, selecting Add Item, targeting a class and giving it the name TestClass.
I go to Project > MyPackage Properties... > Application (tab) > Assembly Information, and I manually update the version patch number by one. So now it is 1.0.5.
I go to the project directory in the Developer Command Line and run the following command: C:\Users\jptak\Downloads\nuget.exe pack -Version 1.0.5
Then I run the following command to push the update (Success message: Your package was pushed.): C:\Users\jptak\Downloads\nuget.exe push MyPackage.1.0.5.nupkg MySecretCodeGoesHere -src http://my.nuget.server.goes.here.com
I go back to ConsoleApp5, Manage NuGet Packages, see the update in the appropriate package, and click the update arrow. The download completes and the new version number is there.
I go to use new classes or check that old errors are fixed and all of my tests fail. TestClass is not there.
This leads me to believe that the code I am writing is not making it to the NuGet server. Does anyone know what I am missing from this process to make the most recent version of the code get updated on the server?
This process is foreign to me as I am not a .NET developer (I work with PHP mostly).
Here are some more pieces of information about my IDE settings:
In Build > Configuration Manager... > Debug has been switched to Release
I have tried building, rebuilding, and cleaning my project. I haven't seen that any of these processes has had any effect on the code being pushed at all.
Here is the code from my ConsoleApp5:
namespace ConsoleApp5
{
class Program
{
static void Main(string[] args)
{
string testclient = "testclient";
string testpass = "testpass";
string scope = "validate-contract";
string accessToken = "";
string retrievedScope = "";
MyPackage.TestClass test = new MyPackage.TestClass();
}
}
Error: TestClass does not exist in namespace. Did you forget an Assembly Reference?
Here's the TestClass code in MyPackage:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MyPackage
{
public class TestClass
{
public TestClass()
{
}
}
}
The NuGet server I'm using is: https://github.com/Daniel15/simple-nuget-server
EDIT 1
Upon inspecting the .nupkg file, I can confirm that the old code is still there and that the new code has not made it into the .nupkg. This seems to support the idea that the problem is with the packaging process and not on the nuget server. How does one refresh the dll files before each nuget pack / nuget push?
Bit long for a comment, not exactly an answer but here we go:
So top debugging tips for NuGet packages are:
Download the package manually. A .nupkg file is just a zip file that can be opened with 7Zip or any other archive tool.
Once inside you can inspect both the .nuspec file that has been used to pack the package, and inside the lib folder are the dlls that have been supplied.
A decompiler like DotPeek or ILSpy can be used on the dll to see exactly what is going on inside the dll.
Possible causes of your symptoms could include the NuGet server giving a false success, or your application failing to update the package and still refering to the old one.

Getting an embedded resource from a shared project

I'm working on a Xamarin Forms app which has two projects, an Android App and an iOS app. All the other code is stored in shared projects.
Solution looks like this:
MyApp.Android (Android project), references MyApp.Base
MyApp.iOS (iOS project), references MyApp.Base
MyApp.Base (Shared project)
I am using the following code to read an SVG image from the shared project:
using (var stream = GetType().Assembly.GetManifestResourceStream("MyApp.Base.image.svg"))
{
// do work here...
}
This works perfectly when the image is in the Android or iOS project, but I want the image to be shared so I put it in the shared project.
GetType().Assembly return MyApp.Android, thus it cannot find the image. I suppose I'm overlooking something but I haven't been able to find a solution.
Can anyone point me in the right direction? Thanks!
You are using the Shared Project NOT the PCL or .Net Standard library. So, all of your Shared Project contents will get merged into the Platform specific project when you Compile them. That means - even if you Embed your resource in your MyApp.Base that will get merged into .iOS/.Droid project.
I suggest you to learn more about Shared Project vs PCL or .Net Standard library.
Below code; I did't tested but this is the direction that you should follow:
#if __IOS__
var resourcePrefix = "MyApp.iOS.";
#endif
#if __ANDROID__
var resourcePrefix = "MyApp.Android.";
#endif
var assembly = IntrospectionExtensions.GetTypeInfo(typeof(SharedPage)).Assembly;
Stream stream = assembly.GetManifestResourceStream
(resourcePrefix + "image.svg");
For more information please look into this page : https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/files?tabs=macos#embedding-in-shared-projects

.NET Core, .NET Standard and Transitive Dependencies across Solutions

My question is similar to this one, although it doesn't really address my issue.
I am working on some new AWS Lambda functions, and I would like to keep their implementation in separate class libraries for reuse. I'm testing this concept using two solutions:
A solution with a single .NET Standard class library project. This class library has a reference to HTML Agility Pack.
A solution with a single .NET Core 2.0 console application project.
Class library:
using System;
using HtmlAgilityPack;
namespace ClassLibrary1
{
public class Class1
{
public static bool FoundDotNet(string html)
{
bool foundDotNet = false;
HtmlDocument document = new HtmlDocument();
document.LoadHtml(html);
var titleNode = document.DocumentNode.SelectSingleNode("//title");
if (titleNode != null)
{
string titleText = titleNode.InnerText;
if (titleText.ToLower().Contains(".net"))
{
foundDotNet = true;
}
}
return foundDotNet;
}
}
}
Console application:
using System;
namespace TestConsole
{
class Program
{
static void Main(string[] args)
{
var foundDotNet = ClassLibrary1.Class1.FoundDotNet("<html><head><title>.NET WTF Buddy</title></head><body>You're doin' me a confuse.</body></html>");
Console.WriteLine(foundDotNet);
}
}
}
Both projects build without issue. However, the HTML Agility Pack assembly isn't copied into the Debug directory for either of the projects, and when I try to run the console application, I get Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'HtmlAgilityPack'
I have the package management format set to "PackageReference" for both projects, which I thought would handle the transitive dependency correctly. HTML Agility Pack is listed in the json.deps file, so I'm not sure what the problem is.
"HtmlAgilityPack/1.7.1": {
"dependencies": {
"System.Net.Http": "4.3.2",
"System.Xml.XPath": "4.3.0",
"System.Xml.XPath.XmlDocument": "4.3.0",
"System.Xml.XmlDocument": "4.3.0"
}
If I move the the class library project into the same solution as the console application, it works fine. What's preventing me from separating my code into separate solutions?
I'm using a large, complicated library in several solutions and the library has many transitive dependencies.
First, set up your library. Right click on the library's project name and choose Properties. About halfway down you'll see a tab labeled Packages. You can use that to auto-generate the NuGet package every time you rebuild the project. Just increment the version number. I use four position version numbering -- the first three are semver-style (major release, minor release, patch release), and the fourth one I increment manually for each new build.
I recommend creating a folder on your drive or network specifically for your local NuGet packages. You can create folders under that for each project. Then you point your debug and release build output to that project folder, and the NuGet package will be generated there, too.
Finally, back in Visual Studio, go to Tools -> Options -> NuGet Package Manager -> Package Sources and add that top-level folder as a package source.
From there it's simple -- open your NuGet dependencies in your consuming app. There's a drop-down at the top right where you can choose the package source. It will automatically search all the child folders and find whatever packages you've created. Now when you tweak your library, it's just a single click to update the client apps.

Is it possible to create a Portable class library with Roslyn?

This is a very simple code that generates a dll that can be referenced from a Portable class library, but, it is prone error because when I add any reference it accepts non portable references.
How can I tell for sure that what I'm trying to generate is on the Portable profile?,
Here is the code:
using System.IO;
using Roslyn.Compilers;
using Roslyn.Compilers.CSharp;
namespace Ros1
{
class Program
{
static void Main(string[] args)
{
SyntaxTree tree = SyntaxTree.ParseText(
#"using System;
namespace HelloWorld
{
public class A
{
public int Sum(int a, int b)
{
return a + b;
}
}
}");
var co = new CompilationOptions(OutputKind.DynamicallyLinkedLibrary);
var compilation = Compilation.Create("HelloWorld", co)
.AddReferences(MetadataReference.CreateAssemblyReference("mscorlib"))
.AddSyntaxTrees(tree);
using (var file = new FileStream("Sum.dll", FileMode.Create))
{
compilation.Emit(file);
}
}
}
}
Yes. Portable Class Libraries (PCL) as a concept is transparent to the compiler. It's basically a project system and reference assemblies feature only. If you want to create a portable class library that targets, say .NET for Windows Store apps and .NET 4.5, you should compile against the assemblies in this folder:
%ProgramFiles(x86)%\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5\Profile\Profile7
Every profile folder has a subdirectory called SupportedFrameworks which indicates which frameworks it supports.
To make the PCL work great in Visual Studio, you should also include the TargetFrameworkAttribute. Make sure version and profile are set correctly. For the example above you would need
[assembly: TargetFramework(".NETPortable,Version=v4.5,Profile=Profile7",
FrameworkDisplayName=".NET Portable Subset")]
I don't think we ship these assemblies outside of Visual Studio, so you will need an installation of Visual Studio 2010 (with the PCL extension installed) or Visual Studio 2012.
I believe Paulo's asking whether it is possible to use Roslyn in a Silverlight/portable app. The answer is no, Roslyn currently only works in full trust on desktop CLR. It's certainly something we'd like to enable in future.

Categories

Resources