System.Data.Entity.Design.PluralizationServices Error in Mono - c#

I have a mature C# application that has always been run on Windows that is being ported to Linux (on Mono), and I am running into an error that I cannot resolve regarding PluralizationServices in System.Data.Entity.Design.
The line of code causing the problems is as follows:
PluralizationService pluralizationService = PluralizationService.CreateService(System.Globalization.CultureInfo.InvariantCulture);
Although this has never caused any problems on the Windows application running under Microsoft.NET, when the program is running under Mono I get the following error:
Unhandled Exception:
System.IO.FileNotFoundException: Could not load file or assembly 'System.Data.Entity.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' or one of its dependencies.
File name: 'System.Data.Entity.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
I found here someone else who seemed to be having a similar problem had simply copied the .NET version of the .dll over to their Mono project, and it resolved the issue for them. I tried the same, however I then encountered the following error:
Unhandled Exception:
System.TypeInitializationException: An exception was thrown by the type initializer for MudSharp.Framework.LanguageHelpers ---> System.InvalidProgramException: Invalid IL code in System.Data.Entity.Design.PluralizationServices.PluralizationService:CreateService (System.Globalization.CultureInfo): method body is empty.
I'm using Mono 3.10 on Ubuntu. I can't find any suggestion that Mono doesn't support these functions, and I'm simply unsure how to proceed with debugging this issue.
Any help would be appreciated.

Looks like latter versions of Mono do support the PluralizationService - see function support status.
However, the PluralizationService currently only supports English.
Have you tried this:
PluralizationService pluralizationService = PluralizationService.CreateService(CultureInfo.GetCultureInfo("en-us"));`
FYI, looks easy enough to extend to other languages using the EntityModelSchemaGenerator class.

Plurally is a Mono-compatible replacement to the Entity Framework pluralization services.
use Plurally test library source code jsonclassgenerator
IDE: Xamarin Studio 6.1.3
framework: Mono / .NET 4.5
add NuGet package: Newtonsoft.Json, Plurally
JsonClassGenerator.cs line 10,39
use Plurally.Pluralizer
using Plurally;
private Pluralizer pluralizationService = new Pluralizer(new CultureInfo("en-us"));
JsonType.csline 8
using Plurally;
Xamasoft.JsonClassGenerator.JsonClassGenerator GenerateClasses Result
{
"UserAccount": "",
"UserPassword": "",
"ExtraInfo": ""
}
// Generated by Xamasoft JSON Class Generator
// http://www.xamasoft.com/json-class-generator
using System;
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
namespace CommonModels
{
public class loginArgs
{
public string UserAccount { get; set; }
public string UserPassword { get; set; }
public string ExtraInfo { get; set; }
}
}

Related

Runtime error with a very basic reflection example in C#

I'm trying to learn a bit more about System.Reflection using the official microsoft docs. Specifically I'm trying to run the following example:
// Loads an assembly using its file name.
Assembly a = Assembly.LoadFrom("MyExe.exe");
// Gets the type names from the assembly.
Type[] types2 = a.GetTypes();
foreach (Type t in types2)
{
Console.WriteLine(t.FullName);
}
So I made a new console app using dotnet new console -o=customconsole. I then removed ImplicitUsings from my project file (because I don't like that), and came up with the following code:
using System;
using System.Reflection;
namespace get_type_from_assembly
{
internal class Program
{
static void Main(string[] args)
{
// load assembly using full file name
Assembly a = Assembly.LoadFrom("C:\\Users\\bobmarley\\desktop\\temp\\csharp-reflection\\get-type-from-assembly\\bin\\Debug\\net6.0\\console-custom.exe");
// get type names from assembly
Type[] types2 = a.GetTypes();
foreach (Type t in types2)
{
Console.WriteLine(t.FullName);
}
}
}
}
Then I tried to run the generated executable using dotnet run --project=customconsole. I got the following runtime error:
Unhandled exception. System.BadImageFormatException: Bad IL format. The format of the file 'C:\Users\bobmarley\desktop\temp\csharp-reflection\get-type-from-assembly\bin\Debug\net6.0\console-custom.exe' is invalid.
at System.Runtime.Loader.AssemblyLoadContext.LoadFromPath(IntPtr ptrNativeAssemblyLoadContext, String ilPath, String niPath, ObjectHandleOnStack retAssembly)
at System.Runtime.Loader.AssemblyLoadContext.LoadFromAssemblyPath(String assemblyPath)
at System.Reflection.Assembly.LoadFrom(String assemblyFile)
at get_type_from_assembly.Program.Main(String[] args) in C:\Users\bobmarley\desktop\temp\csharp-reflection\get-type-from-assembly\Program.cs:line 11
make: *** [Makefile:5: run] Error 1
I'm not sure why this occurs, because I checked and the executable does exist in the specified path. What is happening here and how can I fix it?
A likely reason is that the your project and the loaded assembly target different platforms, i.e. x86 vs x64, In my experience that is a common reason for BadImageFormatException. Another possible reasons is that one targets .net core while the other targets .net framework.
Dynamically loading an assembly will require that it is compatible with your project. If you want to read arbitrary assemblies you probably want some tool that can extract whatever information you are after from the CIL code directly, without actually loading it.

Roslyn compilation - how to reference a .NET Standard 2.0 class library

I created a console application project (targeting .NET Core 3.0) and a class library (targeting .NET Standard 2.0). The console application tries to use the Roslyn compiler to compile some C# code that references that previously created class library. I'm hitting some major issues though.
Here's the code for the console application (note that most of it is example code from https://github.com/joelmartinez/dotnet-core-roslyn-sample/blob/master/Program.cs):
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp; //nuget Microsoft.CodeAnalysis.CSharp
using Microsoft.CodeAnalysis.Emit;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
//This is a class library I made in a separate project in the solution and added as a reference to the console application project.
//The important bit for the reproduction of the issue is that ClassLibrary1 targets .NET Standard 2.0.
using ClassLibary1;
namespace RoslynIssueRepro
{
class Program
{
static void Main(string[] args)
{
string codeToCompile =
#"
using ClassLibary1;
using System;
namespace RoslynCompileSample
{
public class Writer
{
public void Execute()
{
//1. this next line of code introduces the issue during Roslyn compilation (comment it out and everything runs fine).
//It causes the code to reference a .NET Standard 2.0 class library (and this console app targets .NET Core 3.0).
//Note: If the referenced class library targets .NET Core 3.0, everything works fine.
//The error looks like this:
// CS0012: The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'.
Console.WriteLine(Class1.DoStuff());
Console.WriteLine(""Freshly compiled code execution done!"");
}
}
}";
var refPaths = new[] {
typeof(System.Object).GetTypeInfo().Assembly.Location,
typeof(Console).GetTypeInfo().Assembly.Location,
Path.Combine(Path.GetDirectoryName(typeof(System.Runtime.GCSettings).GetTypeInfo().Assembly.Location), "System.Runtime.dll"),
typeof(Class1).GetTypeInfo().Assembly.Location,
//2. So adding a reference to netstandard.dll to alleviate the issue does not work.
//Instead it causes even more compilation errors of this form:
// CS0518: Predefined type 'System.Object' is not defined or imported
// CS0433: The type 'Console' exists in both 'System.Console, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' and 'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'
//Go ahead and try it by uncommenting the line below:
//Environment.ExpandEnvironmentVariables(#"C:\Users\%USERNAME%\.nuget\packages\netstandard.library\2.0.0\build\netstandard2.0\ref\netstandard.dll")
};
RoslynCompileAndExecute(codeToCompile, refPaths);
}
#region example code from https://github.com/joelmartinez/dotnet-core-roslyn-sample/blob/master/Program.cs
private static void RoslynCompileAndExecute(string codeToCompile, string[] refPaths)
{
Write("Let's compile!");
Write("Parsing the code into the SyntaxTree");
SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(codeToCompile);
string assemblyName = Path.GetRandomFileName();
MetadataReference[] references = refPaths.Select(r => MetadataReference.CreateFromFile(r)).ToArray();
Write("Adding the following references");
foreach (var r in refPaths)
Write(r);
Write("Compiling ...");
CSharpCompilation compilation = CSharpCompilation.Create(
assemblyName,
syntaxTrees: new[] { syntaxTree },
references: references,
options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
using (var ms = new MemoryStream())
{
EmitResult result = compilation.Emit(ms);
if (!result.Success)
{
Write("Compilation failed!");
IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic =>
diagnostic.IsWarningAsError ||
diagnostic.Severity == DiagnosticSeverity.Error);
foreach (Diagnostic diagnostic in failures)
{
Console.Error.WriteLine("\t{0}: {1}", diagnostic.Id, diagnostic.GetMessage());
}
}
else
{
Write("Compilation successful! Now instantiating and executing the code ...");
ms.Seek(0, SeekOrigin.Begin);
Assembly assembly = AssemblyLoadContext.Default.LoadFromStream(ms);
var type = assembly.GetType("RoslynCompileSample.Writer");
var instance = assembly.CreateInstance("RoslynCompileSample.Writer");
var meth = type.GetMember("Execute").First() as MethodInfo;
meth.Invoke(instance, null);
}
}
}
static Action<string> Write = Console.WriteLine;
#endregion
}
}
and the code for the ClassLibrary1 is just this:
namespace ClassLibary1
{
public static class Class1
{
public static string DoStuff()
{
return "asdfjkl";
}
}
}
I've commented two places in code with //1 and //2. The first one is the line that introduces the first issue, and causes the compilation to fail. The second spot (currently commented out) is an attempt to work around the first issue by adding a reference to the netstandard.dll file (sorry if the path isn't portable, just where I happened to find it on my machine), but it does not fix anything, only introducing more cryptic errors.
Any idea on the approach I should take to get this code to work?
The first error occur because your referenced library targets netstandard and the console app compilation which references this library must reference netstandard.dll to correctly resolve all corresponding types. So you should add reference to nestandard.dll but it's not all and here you get the second error.
When you try to reference netsandard directly or by transitive you must provide the nestandard.dll corresponding by the target platform. And this netstandard will have a huge of forwarding types to the types on the current target platform. If you look at the #"C:\Users\%USERNAME%\.nuget\packages\netstandard.library\2.0.0\build\netstandard2.0\ref\netstandard.dll" you will find that this netstandard.dll doesn't contain forwards but contains all types directly and of course it contains System.Console. ( I think, it contains all types directly because it is from nuget package which doesn't depend on any target platform, but really not sure for that). And when you try to add it and System.Console.dll by typeof(Console).GetTypeInfo().Assembly.Location you actually get two System.Console in a compilation.
So to resolve this ambiguous you can add netstandard not from this nuget package, but from you current target platform which has all needed forwards. For the .netcore30, for example, you can use netstandard from path_to_dotnet_sdks\packs\Microsoft.NETCore.App.Ref\3.0.0\ref\netcoreapp3.0\ (be careful this assemblies and assemblies from nuget package above just for referencing, they doesn't contain real logic). Also you may try to remove reference on System.Console.dll and keep reference on #"C:\Users\%USERNAME%\.nuget\packages\netstandard.library\2.0.0\build\netstandard2.0\ref\netstandard.dll"
Since you're using typeof(X).Assembly to locate all other referenced assemblies, which will implicitly return the assemblies loaded into your App Domain. I would recommend locating the matching netstandard in the same way. However, since netstandard doesn't directly define any types, the best method I've found is to search for it by name;
AppDomain.CurrentDomain.GetAssemblies().Single(a => a.GetName().Name == "netstandard")
var dd = typeof(Enumerable).GetTypeInfo().Assembly.Location;
var coreDir = Directory.GetParent(dd);
MetadataReference.CreateFromFile(coreDir.FullName + Path.DirectorySeparatorChar + "netstandard.dll")
Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(), "netstandard.dll")

Decompiled Sources only show "throw null" for every .NET Framework class

I have
installed Visual Studio Community 2019, version 16.3.3 (including "ASP.NET and Web development" and ".NET Core cross-platform development")
and have checked "Enable Navigation to decompiled Sources",
and created a new ASP.NET Core Web Application (.NET Core 3.0.0)
but when I then look at e.g. the decompiled source for any referenced class in the .NET framework e.g. System.Console or for Microsoft.AspNetCore.Builder (or almost any other type), all I can see for every method's body is throw null (I showed an extract below)
I have read this question (update: and the answer to the question it was a duplicate to), but there only one class had this problem (because it was added in an incremental update). For me, this problem applies to every class in the .NET framework. What am I doing wrong? Is this expected behaviour and I should use something like dotPeek?
Can I use a symbols server instead of decompiled sources?
(Forgive my ignorance, I'm really new to C#... and the .NET world)
region Assembly System.Console, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
// C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\3.0.0\ref\netcoreapp3.0\System.Console.dll
// Decompiled with ICSharpCode.Decompiler 4.0.0.4521
#endregion
using System.IO;
using System.Text;
namespace System
{
// Summary:
// ....
public static ConsoleColor BackgroundColor
{
get
{
throw null;
}
set
{
}
}
//
// Summary:
//...
public static int BufferHeight
{
get
{
throw null;
}
set
{
}
}
...

SQLite3 Connection Causes Confusing Compile Error

I am attempting to compile my Xamarin project and I am getting a compiler error that I dont understand. What does the following error mean and how can i fix this?
Data\SQLiteClient.cs(4,4): Error CS0012: The type 'System.Threading.Tasks.TaskScheduler' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Threading.Tasks, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. (CS0012) (DtoToVm.Droid)
Relevant information:
Xamarin Forms blank project PCL
Project set to .NET 4.5 or later
Profile: PCL 4.5 - Profile78
Alot of references are not happy but I haven't manually setup or editted these. Maybe a nuget package conflict?
using Xamarin.Forms;
using DtoToVm.Droid.Data;
[assembly: Dependency (typeof(SQLiteClient))]
namespace DtoToVm.Droid.Data
{
using System;
using DtoToVm.Data;
using SQLite.Net.Async;
using System.IO;
using SQLite.Net.Platform.XamarinAndroid;
using SQLite.Net;
public class SQLiteClient : ISQLite
{
public SQLiteAsyncConnection GetConnection ()
{
var sqliteFilename = "Conferences.db3";
var documentsPath = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
var path = Path.Combine (documentsPath, sqliteFilename);
var platform = new SQLitePlatformAndroid ();
var connectionWithLock = new SQLiteConnectionWithLock (
platform,
new SQLiteConnectionString (path, true));
// The below line causes the compile error
var connection = new SQLiteAsyncConnection (() => connectionWithLock);
return connection;
}
}
}
Edit:
According to this thread I shd change the profile to 7. I've done this and it got rid of all errors but produced a new one:
DtoToVm\packages\Microsoft.Net.Http.2.2.29\lib\portable-net40+sl4+win8+wp71+wpa81\System.Net.Http.dll: Error CS1703: An assembly with the same identity 'System.Net.Http, Version=1.5.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' has already been imported. Try removing one of the duplicate references. (CS1703) (DtoToVm)
What file could this duplicate reference be in?
I don't really know if System.Threading.Tasks namespace exists in Xamarin or not, If it's exists then reference it, If not then use the regular SqliteConnection and don't use Async one.

System.MissingMethodException with Miniprofiler.Windows

Recently in my WinForm project, I installed MiniProfiler.Windows and write following decorator for my QueryHandlers(I'm using CQRS):
public class MiniProfilerQueryHandlerDecorator<TQuery,TResult>:IQueryHandler<TQuery,TResult> where TQuery : IQueryParameter<TResult>
{
private readonly IQueryHandler<TQuery, TResult> _decoratee;
public MiniProfilerQueryHandlerDecorator(IQueryHandler<TQuery, TResult> decoratee)
{
_decoratee = decoratee;
}
public TResult Handle(TQuery request)
{
TResult result;
using (StackExchange.Profiling.MiniProfiler.Current.Step("Call QueryHandler"))
{
result =_decoratee.Handle(request); //call some Linq to entity queries
}
var friendlyString = ConsoleProfiling.StopAndGetConsoleFriendlyOutputStringWithSqlTimings();
Debug.WriteLine(friendlyString);
return result;
}
}
I get following error at var friendlyString=ConsoleProfiling.StopAndGetConsoleFriendlyOutputStringWithSqlTimings()
line.
An unhandled exception of type 'System.MissingMethodException' occurred in IASCo.Application.Core.dll
Additional information: Method not found: 'Boolean StackExchange.Profiling.MiniProfiler.get_HasSqlTimings()'.
Does anyone know where is the problem?
MissingMethodException = an attempt is made to dynamically access a deleted or renamed method of an assembly that is not referenced by its strong name (msdn).
Or as this answer puts it:
This is a problem which can occur when there is an old version of a DLL still lingering somewhere around
I notice that the MiniProfiler.Windows library is using a very old (over 2 years) version of MiniProfiler. That version of the code did indeed have a MiniProfiler.HasSqlTimings property. However, the current version (3.0.11) no longer has this property.
I am guessing that you are using the code from the MiniProfiler.Windows library that you linked above, but instead of using the v2 MiniProfiler dll that they have saved in /packages, you are using a v3 MiniProfiler dll (maybe downloaded from nuget). This would explain the exception that you are getting.
If this is indeed the case, then you can solve this by either downloading the version 2.0.2 nuget (Install-Package MiniProfiler -Version 2.0.2) or by upgrading the code in ConsoleProfiling to be compatible with MiniProfiler v3.

Categories

Resources