Adding Akavache Static Linker class or Initializer error - c#

I'm currently using Visual Studio Mac 2019 for to build my iOs Xamarin Forms Application.
My Application Akavache to store persistent data specifically credentials which I utilizes its BlobCache.Secure storage, but sadly the data doesn't persist.
I found that I should add either of the following:
1. Linker Class
using System;
using Akavache.Sqlite3;
namespace NameSpace.iOS
{
[Preserve]
public static class LinkerPreserve
{
static LinkerPreserve()
{
var persistentName = typeof(SQLitePersistentBlobCache).FullName;
var encryptedName = typeof(SQLiteEncryptedBlobCache).FullName;
}
}
public class PreserveAttribute : Attribute
{
}
}
or
2. Initializer
Akavache.Registrations.Start("FollowTheDrop");
Akavache: saved value not available after iOS app restart
but every time I add the solution above the following error below occurs during the build
MTOUCH : error MT2101: Can't resolve the reference 'System.Int32
SQLitePCL.raw::sqlite3_bind_blob(SQLitePCL.sqlite3_stmt,System.Int32,System.Byte[])',
referenced from the method 'System.Void
Akavache.Sqlite3.BulkInsertSqliteOperation/<>c__DisplayClass7_0::b__0()'
in 'SQLitePCLRaw.core, Version=1.1.13.388, Culture=neutral,
PublicKeyToken=1488e028ca7ab535'.
Am I missing something that causes this error?

It was solved by updating the following Nuget Packages below which has dependencies on each other:
Akavache 9.0.1
Splat 14.3.1
fusillade 2.4.47
Lastly when adding the linker static class consider adding a Preserve Attribute as shown below:
[Preserve]
public static class LinkerPreserve
{
static LinkerPreserve()
{
var persistentName = typeof(SQLitePersistentBlobCache).FullName;
var encryptedName = typeof(SQLiteEncryptedBlobCache).FullName;
}
}
public class PreserveAttribute : Attribute
{
}

Related

C# System.MissingFieldException on an existing field

I am using C# 4.7.2 an PRISM Unity 6.2.0
I got a public class like this
public partial class MyClass
{
public static string MyFirstString = "MyFirstString";
public static string MySecondString = "MySecondString";
}
The strings are used to register types
public void Initialize()
{
RegisterObjects();
}
private void RegisterObjects()
{
container.RegisterType<object, SomeClass>( MyClass.MyFirstString );
container.RegisterType<object, SomeOtherClass>( MyClass.MySecondString );
}
container is an IUnityContainer, Initiliaze() is a member of IModule (from PRISM)
SomeClass is registered without any problems. But SomeOtherClass can not be registered. A System.MissingFieldException is thrown on MyClass.MySecondString.
Everything is public, the build succeeds, one can even navigate to MySecondString by pressing F12 (in Visual Studio).
What could cause this exception?
It sounds like you have multiple versions of the DLL loaded in your cache. Use "gacutil -l " to see how many version are loaded in your cache. You can use "gacutil -u " to remove all versions.

Xamarin Linking Sdk Assemblies Only - using AssemblyName vs AssemblyName.Class.Method

I have a DLL MyAssemblyOne.dll which only contains one class with static methods:
namespace MyAssemblyOne
{
public class MyClassOne
{
public static string MyStaticMethod()
{
...
}
}
}
All is good so far, the assembly MyAssemblyOne.dll is generated.
Now I have another DLL, MyAssemblyTwo.dll which has a dependency on MyAssemblyOne.dll and uses it like:
no using here;
namespace MyAssemblyTwo
{
public class MyClassFromAssemblyTwo
{
public string SomeRandomMethod()
{
...
var smth = MyAssemblyOne.MyClassOne.MyStaticMethod();
...
}
}
}
Now I create a Xamarin project with Linking set to Sdk Assemblies Only and Use Shared Runtime disabled(basically Release mode), and I add my two DLLs - MyAssemblyTwo.dll and MyAssemblyOne.dll. The app builds ok, but when I run it I get something like:
cannot find MyAssemblyOne.dll.
Please note that this works if the Linking option is set to None.
However, if I change MyAssemblyTwo usage of MyAssemblyOne to be:
using MyAssemblyOne;
namespace MyAssemblyTwo
{
public class MyClassFromAssemblyTwo
{
public string SomeRandomMethod()
{
...
var smth = MyClassOne.MyStaticMethod();
...
}
}
}
everything works fine even with the Linking set to Sdk Assemblies Only.
How does the linker work? Why if I have a using statement everything is fine, but if I use the assembly name directly in the code it breaks.
It is worth mentioning that MyAssemblyOne and MyAsseblyTwo are .netstandard20 projects.

How to use MethodDecorator.Fody Decorator in another project

I used Fody Nuget package as follows
Install package
PM> Install-Package MethodDecorator.Fody
Decorate the method
public class BusinessLayerClass
{
[LogMethod]
public string BusinessLayerMethod()
{
DataLayerClass dataLayerClass = new DataLayerClass();
return dataLayerClass.DataLayerMethod();
}
}
Write the interceptor
using System;
using System.Reflection;
[module: LogMethod] // Attribute should be "registered" by adding as module or assembly custom attribute
// Any attribute which provides OnEntry/OnExit/OnException with proper args
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Assembly | AttributeTargets.Module)]
public class LogMethodAttribute : Attribute, IMethodDecorator
{
private MethodBase _method;
// instance, method and args can be captured here and stored in attribute instance fields
// for future usage in OnEntry/OnExit/OnException
public void Init(object instance, MethodBase method, object[] args)
{
_method = method;
}
public void OnEntry()
{
NLogging.Trace("Entering into {0}", _method.Name);
}
public void OnExit()
{
NLogging.Trace("Exiting into {0}", _method.Name);
}
public void OnException(Exception exception)
{
NLogging.Trace(exception, "Exception {0}", _method.Name);
}
}
This works fine within the same project but when I use the decorator [LogMethod] in another method in another project, this OnEntry(), OnExit(), OnException(Exception exception) methods do not fire.
For instance:
[LogMethod]
public void Another_Method_In_Seperate_Project()
I added a reference to the project where [LogMethod] is defined.
Could anyone please send me a way of using the same implementation in other projects without doing the implementation of LogMethodAttribute.cs (where this [LogMethod] is defined) in each and every project.
You need to install MethodDecorator.Fody nuget package in the other project as well (along with dependencies). You will also need to add another FodyWeavers.xml in that project.
In addition to the answer by H.D. I recommend looking at this answer, from another post: https://stackoverflow.com/a/61503942/13081132
Edit:
The answer I have linked to simply reminds the author to "register" the attribute inside the file where the attributes is being used.
Example:
[module: LogMethod] // In my case this was nessesary for all files using the attribute
public class BusinessLayerClass
{
[LogMethod]
public string BusinessLayerMethod()
{
DataLayerClass dataLayerClass = new DataLayerClass();
return dataLayerClass.DataLayerMethod();
}
}

HttpContext.GetGlobalResourceObject not exist in Class Library

I'm writing various class libraries (tools and helpers) for my future ASP.Net project.
Right now my solution doesn't have web project, but it's not supposed to be a problem.
I added reference to System.Web to project and now I able to access HttpContext in code.
Below my code for resource manager class that suppose to get application global resources:
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
namespace ResourceManager
{
public class ResourceManager : IResourceManager
{
HttpContext context;
public ResourceManager(HttpContext ctx)
{
context = ctx;
}
public string GetError(string key)
{
return context.GetGlobalResourceObject("Errors", key).ToString();
}
//And so on........
}
}
But unfortunately Visual Studio intellisense can't find GetGlobalResourceObject.
Hitting F12 and I can see this static function inside HttpContext class.
After running build I'm getting this error message:
Member 'HttpContext.GetGlobalResourceObject(string, string)' cannot be accessed with an instance reference; qualify it with a type name instead
It's strange behaviour and interesting for me why it's happening.
Thanks for help
This is untested, but from the error message I think the usage should be as below.
Essentially you just use the static HttpContext rather than creating an instance of it.
using System.Web;
namespace ResourceManager
{
public class ResourceManager : IResourceManager
{
public string GetError(string key)
{
return HttpContext.GetGlobalResourceObject("Errors", key).ToString();
}
//And so on........
}
}

EntityFramework.Migrations, using DbMigrator in a C# class

I just installed the new EntityFramework.Migrations package. I scaffoled my migrations following this tutorial: http://blogs.msdn.com/b/adonet/archive/2011/09/21/code-first-migrations-alpha-3-no-magic-walkthrough.aspx
Using the Powershell window, everything works fine.
But we need to create a class that will rollback all the migrations for our automated tests.
So I made a simple class that looks like this:
public class CustomMigrator
{
public void DropDatabase()
{
new DbMigrator(new Settings()).Update("0");
}
public void RegenerateDatabase()
{
new DbMigrator(new Settings()).Update();
}
}
Settings is my DbMigrationContext implementation that looks like this:
public class Settings : DbMigrationContext<MyDb>
{
public Settings()
{
AutomaticMigrationsEnabled = false;
SetCodeGenerator<CSharpMigrationCodeGenerator>();
AddSqlGenerator<SqlConnection, SqlServerMigrationSqlGenerator>();
}
}
When I call this:
new CustomMigrator().DropDatabase();
I get a weird exception:
The given assembly name or codebase was invalid. (Exception from HRESULT: 0x80131047)
I know that Migrations are still in alpha, but I was wondering if anyone have been able to run the migrations using DbMigrator?
Thanks.
I just found my problem, it is because I was using EntityFrameworkProfiler and there is a bug with the latest EF release that breaks the profiler.
http://blogs.hibernatingrhinos.com/5121/entity-framework-june-2011-ctp-v4-2-is-now-supported-in-entity-framework-profiler
For the moment I did not need the profiler, so I just removed the line of code that was initializing the profiler and now it works.

Categories