Let say I have this interface in C# and want to implement it in F#
public interface IBatch
{
System.Data.IDbConnection Connection { get; set; }
}
I wish to implement the interface in F# but cant figure out the correct syntax. I have something like this:
type public Batch =
interface IBatch with
member f.Connection
with get() = new Devart.Data.Oracle.OracleConnection()
and set value = ()
The error I'm getting is:
This expression was expected to have type IDbConnection but here has type Devart.Data.Oracle.OracleConnection
F# does not implement implicit downcasting like C# does, you need to have
type public Batch =
interface IBatch with
member f.Connection
with get() = new Devart.Data.Oracle.OracleConnection() :> System.Data.IDbConnection
and set value = ()
Related
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.
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.
I'm loading a .NET assembly dinamically via reflection and I'm getting all the classes that it contains (at the moment one). After this, I'm trying to cast the class to an interface that I'm 100% sure the class implements but I receive this exception: Unable to cast object of type System.RuntimeType to the type MyInterface
MyDLL.dll
public interface MyInterface
{
void MyMethod();
}
MyOtherDLL.dll
public class MyClass : MyInterface
{
public void MyMethod()
{
...
}
}
public class MyLoader
{
Assembly myAssembly = Assembly.LoadFile("MyDLL.dll");
IEnumerable<Type> types = extension.GetTypes().Where(x => x.IsClass);
foreach (Type type in types)
{
((MyInterface)type).MyMethod();
}
}
I have stripped out all the code that is not necessary. This is basically what I do. I saw in this question that Andi answered with a problem that seems the same mine but I cannot anyway fix it.
You are trying to cast a .NET framework object of type Type to an interface that you created. The Type object does not implement your interface, so it can't be cast. You should first create a specific instance of your object, such as through using an Activator like this:
// this goes inside your for loop
MyInterface myInterface = (MyInterface)Activator.CreateInstance(type, false);
myInterface.MyMethod();
The CreateInstance method has other overloades that may fit your needs.
i have a question.i have a method (Filter),i want to pass T dynamic.but it dosen`t accept.how can i do it?
public List<T> Filter<T>(string TypeOfCompare)
{
List<T> ReturnList2 = new List<T>();
return ReturnList2;
}
IList MakeListOfType(Type listType)
{
Type listType1 = typeof(List<>);
Type specificListType = listType.MakeGenericType(listType1);
return (IList)Activator.CreateInstance(specificListType);
}
Filter < ConstructGenericList(h) > ("s");
IList MakeListOfType(Type listType)
{
Type listType1 = typeof(List<>);
Type specificListType = listType.MakeGenericType(listType1);
return (IList)Activator.CreateInstance(specificListType);
}
It should be the other way round, you should call MakeGenericType on the generic type definition, not on the generic type argument. So the code becomes this:
IList MakeListOfType(Type elementType)
{
Type listType = typeof(List<>);
Type specificListType = listType.MakeGenericType(elementType);
return (IList)Activator.CreateInstance(specificListType);
}
(note that I changed the variables names to make the code clearer)
Generic parameters must have a type able to be determined at compile time (without resorting to something like functional type inference that some other languages have). So, you can't just stick a function between the angle brackets to get the type you want.
Edit:
Now that I know what you're trying to do, I would suggest a different approach entirely.
You mention that you are using Entity Framework, and you are trying to use one method to get a list of different types of objects. Those objects -- like Student and Teacher -- must have something in common, though, else you would not be trying to use the same method to retrieve a list of them. For example, you may just be wanting to display a name and have an ID to use as a key.
In that case, I would suggest defining an interface that has the properties common to Student, Teacher, etc. that you actually need, then returning a list of that interface type. Within the method, you would essentially be using a variant of the factory pattern.
So, you could define an interface like:
public interface INamedPerson
{
int ID { get; }
string FirstName { get; }
string LastName { get; }
}
Make your entities implement this interface. Auto-generated entities are (typically) partial classes, so in your own, new code files (not in the auto-generated code files themselves), you would do something like:
public partial class Student : INamedPerson
{
public int ID
{
get
{
return StudentId;
}
}
}
and
public partial class Teacher : INamedPerson
{
public int ID
{
get
{
return TeacherId;
}
}
}
Now, you may not even need to add the ID property if you already have it. However, if the identity property in each class is different, this adapter can be one way to implement the interface you need.
Then, for the method itself, an example would be:
public List<INamedPerson> MakeListOfType(Type type)
{
if (type == typeof(Student))
{
// Get your list of students. I'll just use a made-up
// method that returns List<Student>.
return GetStudentList().Select<Student, INamedPerson>(s => (INamedPerson)s)
.ToList<INamedPerson>();
}
if (type == typeof(Teacher))
{
return GetTeacherList().Select<Teacher, INamedPerson>(t => (INamedPerson)t)
.ToList<INamedPerson>();
}
throw new ArgumentException("Invalid type.");
}
Now, there are certainly ways to refine this pattern. If you have a lot of related classes, you may want to use some sort of dependency injection framework. Also, you may notice that there is a lot of duplication of code. You could instead pass a function (like GetStudentList or GetTeacherList) by doing something like
public List<INamedPerson> GetListFromFunction<T>(Func<IEnumerable<T>> theFunction) where T : INamedPerson
{
return theFunction().Select<T, INamedPerson>(t => (INamedPerson)t).ToList<INamedPerson>();
}
Of course, using this function requires, once again, the type passed in to be known at compile time. However, at some point, you're going to have to decide on a type, so maybe that is the appropriate time. Further, you can make your life a little simpler by leaving off the generic type at method call time; as long as you are passing in a function that takes no arguments and returns an IEnumerable of objects of the same type that implement INamedPerson, the compiler can figure out what to use for the generic type T.
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.)