C# 9 default implementations causing errors [duplicate] - c#-9.0

Here is a my code inside a c# project that targets .NET Core 3.0 (so I should be in C# 8.0) with Visual Studio 2019 (16.3.9)
public interface IJsonAble
{
public string ToJson() => System.Text.Json.JsonSerializer.Serialize(this);
}
public class SumRequest : IJsonAble
{
public int X { get; set; }
public int Y { get; set; }
public void Tmp()
{
new SumRequest().ToJson(); //compile error
}
}
The compile error is:
CS1061 'SumRequest' does not contain a definition for 'ToJson' and no accessible extension method 'ToJson' accepting a first argument of type 'SumRequest' could be found (are you missing a using directive or an assembly reference?)
Can someone shed some light on this behavior ?

Methods are only available on the interface, not the class. So you can do this instead:
IJsonAble request = new SumRequest()
var result = request.ToJson();
Or:
((IJsonAble)new SumRequest()).ToJson();
The reason for this is it allows you to add to the interface without worrying about the downstream consequences. For example, the ToJson method may already exist in the SumRequest class, which would you expect to be called?

Try using (new SumRequest() as IJsonAble).ToJson(); to help the compiler a bit.
Anyway, I'm sure what you're after is (this as IJsonAble).ToJson(), assuming you want to apply ToJson on current SumRequest instance.

Related

Can not access interface default implementation method from within derived class [duplicate]

Here is a my code inside a c# project that targets .NET Core 3.0 (so I should be in C# 8.0) with Visual Studio 2019 (16.3.9)
public interface IJsonAble
{
public string ToJson() => System.Text.Json.JsonSerializer.Serialize(this);
}
public class SumRequest : IJsonAble
{
public int X { get; set; }
public int Y { get; set; }
public void Tmp()
{
new SumRequest().ToJson(); //compile error
}
}
The compile error is:
CS1061 'SumRequest' does not contain a definition for 'ToJson' and no accessible extension method 'ToJson' accepting a first argument of type 'SumRequest' could be found (are you missing a using directive or an assembly reference?)
Can someone shed some light on this behavior ?
Methods are only available on the interface, not the class. So you can do this instead:
IJsonAble request = new SumRequest()
var result = request.ToJson();
Or:
((IJsonAble)new SumRequest()).ToJson();
The reason for this is it allows you to add to the interface without worrying about the downstream consequences. For example, the ToJson method may already exist in the SumRequest class, which would you expect to be called?
Try using (new SumRequest() as IJsonAble).ToJson(); to help the compiler a bit.
Anyway, I'm sure what you're after is (this as IJsonAble).ToJson(), assuming you want to apply ToJson on current SumRequest instance.

Class from Interface.cll

I'm trying to implement a class instance of an interface class. Exploring the interface (.NET DLL) with the project explorer, it says:
bool CreateInstance(SharedLibrary::MemoryArbiter^ pntMemory,
SharedLibrary::clsMessageQueue^ pntMessageQueue,
SharedLibrary::clsGPIO^ pntGPIO,
SharedLibrary::Types^ pntProgramSettings,
SharedLibrary::DisplayDriver^ pntDisplayDriver)
Member from Plugin_Interface::IPlugin
But if I write in my MyClass.h:
using namespace System;
using namespace System::ComponentModel;
using namespace SharedLibrary;
namespace MyCppPlugin {
[AttributeUsageAttribute(AttributeTargets::Class | AttributeTargets::Method |
AttributeTargets::Property | AttributeTargets::Field,
AllowMultiple = true, Inherited = false)]
ref class MyPlugin abstract : public Plugin_Interface::IPlugin
{
bool CreateInstance(SharedLibrary::MemoryArbiter^ pntMemory,
SharedLibrary::clsMessageQueue^ pntMessageQueue,
SharedLibrary::clsGPIO^ pntGPIO, SharedLibrary::Types^
pntProgramSettings, SharedLibrary::DisplayDriver^ pntDisplayDriver);
};
};
It says: "error C3766: Missing implementation of Plugin_Interface::IPlugin::CreateInstace(...)
What the heck do I do wrong?
EDIT:
Forgot the abstract statement.
And: Why is it saying "IntelliSense: Class can not implement interface member function "Plugin_Interface::IPlugin::CreateInstance" (declared in "Plugin_Interface.dll")"
???
You got a lot more diagnostic messages from this snippet, you are making several mistakes:
[AttributeUsage] is only valid on a class that derives from System::Attribute. You no doubt need to use some kind of attribute so that the plugin host can recognize your class as a valid plugin candidate, I can't guess what that attribute might be.
A method that implements an interface method should be public.
A method that implements an interface method must be virtual.
The method signature must be an exact match with the interface method declaration.
Just in case: you must actually implement the method, not just declare it.
The third and forth bullets are the chief reasons for the "must provide an implementation of the interface method" compile error. So proper code ought to resemble something like this:
[NoIdeaWhatAttribute]
public ref class MyPlugin : public Plugin_Interface::IPlugin {
public:
virtual bool CreateInstance(SharedLibrary::MemoryArbiter^% pntMemory,
SharedLibrary::clsMessageQueue^% pntMessageQueue,
SharedLibrary::clsGPIO^% pntGPIO,
SharedLibrary::Types^% pntProgramSettings,
SharedLibrary::DisplayDriver^% pntDisplayDriver)
{
// Todo...
return false;
}
};
I got it. Thanks to Hans Passant who gave me so many hints :)
To export the function it has to implement the Interface 1:1. The export statement has to be added over the class header:
[Export(IPlugin::typeid)]
public ref class MyPlugin : public Plugin_Interface::IPlugin
And: While VB.NET will compile to "Any CPU" and C++/CLI will compile to Win64/Win32 it will missfit. Both Projects have to have the same target - either 64bit OR 32bit.
Now it works.

"Signature of the body and declaration in a method implementation do not match"

UPDATE: I think I've eliminated Unity from the equation. See below for more details.
UPDATE 2: I think I may have eliminated Entity Framework fro the equation. See below for more details.
I have some code that is building a unity container, but it started failing with the above error message out of the blue. It works on other people's machines, but not mine. I deleted the folder the solution was in and refreshed everything from source control to ensure I had nothing that could be causing issues (e.g. duplicate assemblies lying around from a previous build).
Here is part of my code:
public static class UnityBootstrapper
{
public static IUnityContainer Initialise()
{
Trace.WriteLine("UnityBootstrapper.Initialise()");
var container = BuildUnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
return container;
}
private static IUnityContainer BuildUnityContainer()
{
Trace.WriteLine("UnityBootstrapper.BuildUnityContainer()");
var container = new UnityContainer();
// Other dependencies are registered here
// If the following line is commented out the container is build
// but, obviously, it won't resolve this dependency.
container.RegisterType<IUserAccessEntities, UserAccessEntities>(WebRequestLifetime);
// Other dependencies are registered here
return container;
}
The code apparently fails on the call to BuildUnityContainer(), and I can see that the trace statement I put inside that method is never displayed.
However, if I comment out the line that registers the UserAccessEntities class (which was code generated from Entity Framework 5) then the container is built. Naturally, when I ask for that dependency it can't resolve it, so the code just fails elsewhere.
I've Googled for solutions and they all seem to resolve around generics and moving the generic type from the method to the class level. I can't do that as EF5 creates the class and it puts generics on the properties. e.g
DbSet<MyTable> Tables { get; set; }
The only other thing I can think of is that I've extracted an interface from the EF5 generated class called IUserAccessEntities and the problem could lie there... but I used ReSharper to generate that, so it should be perfectly aligned.
UPDATE
Just to eliminate Unity from the equation, I tried to new up the UserAccessEntities on its own
private static void TestUae()
{
var uae = new UserAccessEntities(); //container.Resolve<IUserAccessEntities>();
Trace.WriteLine("Got the entities: " + uae);
}
And the call to TestUae() fails instead.
UPDATE 2
I created a new class, AlternativeEntities based on the interface I'd previously extracted. When I try to construct that directly it has a new exception: Method 'Set' in type 'AlternativeEntities' from assembly 'UserAccess.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.
However, it does. There are two methods called set, both of which I've given a basic implementation:
public class AlternativeEntities : IUserAccessEntities
{
public DbSet<TEntity> Set<TEntity>() where TEntity : class
{
Trace.WriteLine("public DbSet<TEntity> Set<TEntity>() where TEntity : class");
return null;
}
public DbSet Set(Type entityType)
{
Trace.WriteLine("public DbSet Set(Type entityType)");
return null;
}
// Other methods and properties here.
}

Importing dependencies using a class that inherits from Lazy<>

Can you import using a class that inherits from Lazy rather than Lazy itself? I am exporting using a derivitive of ExportAttribute that contains metadata.
[FeatureExport(/* Feature Metadata Parameters */)]
public class Feature : IFeature
{
// Feature Properties
}
public class FeatureReference : Lazy<IFeature, IFeatureMetadata>
{
}
public class Consumer
{
[ImportMany]
public IEnumerable<FeatureReference> FeatureReferences { get; set; }
}
Is this possible? Would it work? I could try it myself, but I'm in development so I don't actually have any code written.
No, it won't work I'm afraid. You would need to implement your own programming model extension (either a custom part/catalog or possibly via ReflectionModelServices) to make this work.
MEF would have to create the FeatureReference object in order to set it, and considering that FeatureReference might have any constructor imaginable, you can guess why this isn't supported.

Reflection / C# typing errors when publishing an F# class implementing an interface

I have an interface written in C#, but when implementing it in F#, I noticed some oddities.
The F# class has to be cast to the interface before C# can consume it
After casting, WPF can't read it's properties (Bindings failed and SNOOP was unable to reflect on it)
I can wrap the object in C# code and everything works fine.
the interface
public interface IInterpret {
public string Name {get;}
public IEnumberable<Project> Interpret(string text);
}
The F# Class
type Interpreter()=
interface IInterpret with
member x.Name = "FParsec Based"
member x.Interpret(str) = Seq.empty
The code below fails to compile
The error is about Interpreter not implementing IInterpert
public ViewModel(){
IInterpret i = new FSharpLib.Interperter();
}
This is my current workaround
public class MyProxy: IInterpret{
private IInterpret _cover;
public MyProxy() {
_cover = new FSharpLib.Interperter() as IInterpret;
}
public string Name { get { return _cover.Name; } }
public IEnumerable<Project> Interpret(string text){
return _cover.Interpret(text);
}
}
Is there something I'm doing wrong with my F# class def, or is the proxy needed? I'm using the current VS2010 f#, not an out of band drop.
F# implements all interfaces explicitly. This means you must explicitly cast to the interface type.
I don't know a ton about WPF binding to explicit interfaces, but see if these
http://leecampbell.blogspot.com/2008/09/generic-binding-in-wpf-through-explicit.html
http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/92a2a3ba-74a6-4c79-9c75-f42d232a4dbf
help? (I just found them Bing-ing for "wpf binding explicit interfaces".)
(Another alternative may be to do something like
type Interpreter()=
member x.Name = "FParsec Based"
member x.Interpret(str:string) = Seq.empty
interface IInterpret with
member x.Name = x.Name
member x.Interpret(str) = x.Interpret(str)
where you "explicitly implement the interface implicitly", if you pardon the confusing terminology.)