I have following C# async interface:
x.BeginOperation(a:sting, b:string, c:string, d:string, g:string, ?q:string) : IAsyncResult
x.EndOperation(result:IAsyncResult) : IEnumerable<string>
I would like to use this in my async workflow and get Async<'T> object that would represent the computation.
I guess that Async.FromBeginEnd is the way to go but I have hard time trying to pass begin/end operation method to it. BeginOperation has too many arguments plus the optional one (plus I don't really manage to wrap my mind around the AsyncCallback * obj in signature).
What is the proper way to get Async from this interface. Thanks.
Assuming that your interface is declared something like this:
type IMyInterface =
abstract member BeginOperation :
(string * string * string * string * string * string option) ->
IAsyncResult
abstract member EndOperation : IAsyncResult -> string seq
you should be able to create an Async<'T> using a little helper function like this:
let toAsync (x : IMyInterface) =
let beginAction (callback, values : obj) =
match values with
| :? (string * string * string * string * string * string option) as v ->
x.BeginOperation v
| _ -> failwith "Unexpected values"
Async.FromBeginEnd (beginAction, x.EndOperation)
The inner beginAction helper function has the signature 'a * obj -> IAsyncResult, which means that it takes a tuple of the generic type 'a (in C# it would typically be denoted as T) and a System.Object, and returns an IAsyncResult instance.
For Async.FromBeginEnd, that's the required signature for the beginAction.
The interface's EndOperation method already has the correct signature, so it can be passed in unmodified.
The entire signature of the toAsync function is IMyInterface -> Async<seq<string>>.
Related
Taking the following minimal example:
type IMyInterface =
interface
abstract member Name: string with get
end
let testInstance =
{ new IMyInterface with
member _.Name = "Hello Word" }
I would have naively expected a call to testInstance.GetType().GetProperties() to contain a PropertyInfo element corresponding to Name.
However, only an empty array is returned.
Using testInstance.GetType().GetProperty("Name") yields no better as it simply returns a <null> object.
More confusing still, Visual Studio 2022 IntelliSense lists Name as a valid property (as I'd expect).
How can I get a PropertyInfo corresponding to the Name property?
In F# all interface implementations are private. This means that interface methods and properties do not appear as methods and properties of the implementing class.
In C# this works a bit differently: if you define a public member that happens to match an interface member, you don't have to explicitly tell the compiler that it's meant to be the interface implementation, the compiler will map it to the interface automatically for you.
So, for example, if you write this:
class MyClass : IMyInterface {
public string Name { get; }
}
The C# compiler will actually compile it as this:
class MyClass : IMyInterface {
public string Name { get; }
string IMyInterface.Name { get { return this.Name; } }
}
(well, it's not exactly like that, but you get the idea)
But the F# compiler doesn't do that. If you want a class property in addition to the interface property, you have to roll one yourself:
type MyClass() =
member __.Name = "Hello Word"
interface IMyInterface with
member this.Name = this.Name
But if you just want the interface property, you can get it off of the interface type:
let nameProp = typeof<IMyInterface>.GetProperty("Name")
let helloWorld = nameProp.GetValue testInstance
Or, if you don't know the interface type in advance, you can get it from the object type as well:
let intf = testInstance.GetType().GetInterfaces().[0]
let nameProp = intf.GetProperty("Name")
let helloWorld = nameProp.GetValue testInstance
I have a problem to understand why the address operator can be used when the return type is an interface
func NewReader() IReader {
return &Reader{}
}
but (of course) not when a return type is a struct
func NewReader() Reader {
return &Reader{} // cannot use &Reader literal (type *Reader) as type Reader in return argument
}
The function signature later is func MyFuncReader(r IReader) but the reflect.TypeOf(r) is *main.Reader.
So the type IReader is hiding the fact that it is pointer?
The function signature func MyFuncReader(r IReader) doesn't tell me, that a pointer or a value was passed the func?
Samples
Full Sample with interface https://play.golang.org/p/1Db1Jybp0rP
Full Sample without interface https://play.golang.org/p/nPtu09yhe0C
If the return type of a function is an interface type, you may return any values that implement that interface. Spec: Return statements:
The return value or values may be explicitly listed in the "return" statement. Each expression must be single-valued and assignable to the corresponding element of the function's result type.
In your first example Reader has methods with pointer receiver, so only a pointer to Reader (that is *Reader) implements the IReader interface. So you have to return &Reader{}.
If your function has a return type of a concrete type, you have to return a value of that exact concrete type, you can't return a value of a pointer to that type.
When the return type is a Reader
func NewReader() Reader {
return &Reader{} // cannot use &Reader literal (type *Reader) as type Reader in return argument
}
you cannot use a pointer to a Reader type in place of a Reader type. The reason being they are just not of the same type.
When you use an interface like IReader as a return type as in
func NewReader() IReader {
return &Reader{}
}
it basically means that any type implementing the methods of the IReader interface will classify as a type implementing that interface and thus will be acceptable. Since the type *Reader implements the IReader type in your example, it is an acceptable return value of the NewReader function here. That means if I introduce a new type which implements this interface, such as,
type dummy int
func (d dummy) GetCount() int {
return d
}
func (d dummy) IncreaseCount() {
fmt.Println("Increased count: %d", d)
}
then I can do something like
func NewReader() IReader {
var d dummy
d = 5
return d
}
and it would still work. The underlying type of this returned value on checking using the reflect package will be dummy.
(This is difficult to search because results are all about "method reference")
I want to get a Method instance for a lambda expression for use with a legacy reflection-based API. The clousure should be included, so calling thatMethod.invoke(null, ...) should have the same effect as calling the lambda.
I have looked at MethodHandles.Lookup, but it only seems to be relevant for the reverse transform. But I guess the bind method may help to include the clousure?
Edit:
Say I have am lambda experssion:
Function<String, String> sayHello = name -> "Hello, " + name;
and I have a legacy framework (SpEL) that has an API like
registerFunction(String name, Method method)
which will call the given Method with no this argument (i.e. Method assumed to be static). So I'll need to get a special Method instance that includes the lambda logic + the clousure data.
In case you don't find an elegant way, here is the ugly way (Ideone). Usual warning when reflection is involved: may break in future releases etc.
public static void main(String[] args) throws Exception {
Function<String, String> sayHello = name -> "Hello, " + name;
Method m = getMethodFromLambda(sayHello);
registerFunction("World", m);
}
static void registerFunction(String name, Method method) throws Exception {
String result = (String) method.invoke(null, name);
System.out.println("result = " + result);
}
private static Method getMethodFromLambda(Function<String, String> lambda) throws Exception {
Constructor<?> c = Method.class.getDeclaredConstructors()[0];
c.setAccessible(true);
Method m = (Method) c.newInstance(null, null, null, null, null, 0, 0, null, null, null, null);
m.setAccessible(true); //sets override field to true
//m.methodAccessor = new LambdaAccessor(...)
Field ma = Method.class.getDeclaredField("methodAccessor");
ma.setAccessible(true);
ma.set(m, new LambdaAccessor(array -> lambda.apply((String) array[0])));
return m;
}
static class LambdaAccessor implements MethodAccessor {
private final Function<Object[], Object> lambda;
public LambdaAccessor(Function<Object[], Object> lambda) {
this.lambda = lambda;
}
#Override public Object invoke(Object o, Object[] os) {
return lambda.apply(os);
}
}
Well, lambda expressions are desugared into methods during compilation and as long as they don’t capture this (don’t access non-static members), these methods will be static. The tricky part is to get to these methods as there is no inspectable connection between the functional interface instance and its target method.
To illustrate this, here the simplest case:
public class LambdaToMethod {
public static void legacyCaller(Object arg, Method m) {
System.out.println("calling Method \""+m.getName()+"\" reflectively");
try {
m.invoke(null, arg);
} catch(ReflectiveOperationException ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) throws URISyntaxException
{
Consumer<String> consumer=s -> System.out.println("lambda called with "+s);
for(Method m: LambdaToMethod.class.getDeclaredMethods())
if(m.isSynthetic() && m.getName().contains("lambda")) {
legacyCaller("a string", m);
break;
}
}
}
This works smoothly as there is only one lambda expression and hence, one candidate method. The name of that method is compiler specific and may contain some serial numbers or hash codes, etc.
On kludge is to make the lambda expression serializable and inspect its serialized form:
static Method lambdaToMethod(Serializable lambda) {
for(Class<?> cl=lambda.getClass(); cl!=null; cl=cl.getSuperclass()) try {
Method m=cl.getDeclaredMethod("writeReplace");
m.setAccessible(true);
try {
SerializedLambda sl=(SerializedLambda)m.invoke(lambda);
return LambdaToMethod.class.getDeclaredMethod(sl.getImplMethodName(),
MethodType.fromMethodDescriptorString(sl.getImplMethodSignature(),
LambdaToMethod.class.getClassLoader()).parameterArray());
} catch(ReflectiveOperationException ex) {
throw new RuntimeException(ex);
}
} catch(NoSuchMethodException ex){}
throw new AssertionError();
}
public static void main(String[] args)
{
legacyCaller("a string", lambdaToMethod((Consumer<String>&Serializable)
s -> System.out.println("first lambda called with "+s)));
legacyCaller("a string", lambdaToMethod((Consumer<String>&Serializable)
s -> System.out.println("second lambda called with "+s)));
}
This works, however, serializable lambdas come at a high price.
The simplest solution would be to add an annotation to a parameter of the lambda expression to be found when iterating over the methods, however, currently, javac doesn’t store the annotation properly, see also this question about this topic.
But you may also consider just creating ordinary static methods holding the code instead of a lambda expression. Getting a Method object for a method is straight-forward and you still can create a functional interface instance out of them using method references…
Since the question mentions SpEL specifically (and I found the question when also working with SpEL), an alternative way to add a custom function to the evaluation context without using Method references is to add a custom MethodResolver (javadoc, GitHub) to the StandardEvaluationContext. A benefit of this approach is that one can add both static and non-static methods to the evaluation context using it, where only static methods could be added using the registerFunction approach.
The code to add a custom MethodResolver to the StandardEvaluationContext is fairly straightforward. Below is an executable example showing how to do so:
public static void main(String[] args) throws Exception {
Function<String, String> sayHello = name -> "Hello, " + name;
// The evaluation context must have a root object, which can be set in the StandardEvaluationContext
// constructor or in the getValue method of the Expression class. Without a root object, the custom
// MethodResolver will not be called to resolve the function.
Object rootObject = new Object();
StandardEvaluationContext standardEvaluationContext = new StandardEvaluationContext(rootObject);
// Add the custom MethodResolver to the evaluation context that will return a MethodExecutor that
// Spring can use to execute the sayHello function when an expression contains "sayHello('<any string>')".
standardEvaluationContext.addMethodResolver((context, targetObject, methodName, argumentTypes) -> {
MethodExecutor methodExecutor = null;
if (methodName.equals("sayHello")
&& argumentTypes.size() == 1
&& String.class.isAssignableFrom(argumentTypes.get(0).getObjectType())
) {
methodExecutor = (innerContext, target, arguments) -> {
final String name = arguments[0].toString();
return new TypedValue(sayHello.apply(name));
};
}
return methodExecutor;
});
// Create an expression parser, parser the expression, and get the evaluated value of the expression.
SpelExpressionParser expressionParser = new SpelExpressionParser();
Expression expression = expressionParser.parseExpression("sayHello('World!')");
String expressionValue = expression.getValue(standardEvaluationContext, String.class);
// Output the expression value, "Hello, World!", to the console.
System.out.println(expressionValue);
}
The value of the expression that was output to the console by executing the above code was:
Hello, World!
Note that when using a MethodResolver to add a function to the evaluation conext, the function should not be prefixed with a # in the expression string. This is a major difference between using the MethodResolver and using the registerFunction method to add a function to the evaluation context.
sayHello('World!') // will work!
#sayHello('World!') // will not work!
Keep this in mind if you are considering migrating an existing solution from using the registerFunction approach to using the MethodResolver approach.
I have a problem with an XML response to a call to the Web API.
Specifically, I have a function "GetValue" call that when I should return in XML format based to the id or class "Cellulare" or class "Televisore".
The problem is that if I make a request from browser gives me the following error:
<Message>An error has occurred.</Message>
<ExceptionMessage>
The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'.
</ExceptionMessage>
This is the example:
Public Class Cellulare
Public Property Colore As String
Public Property SistemaOperativo As String
End Class
Public Class Televisore
Public Property Colore As String
Public Property Marca As String
End Class
Public Function GetValue(ByVal id As Integer) // ' As Cellulare
If Id = 1 Then
Dim MyTelevisore As New Televisore
MyTelevisore.Colore = "grigio"
MyTelevisore.Marca = "lg"
Return MyTelevisore
Else
Dim MyCellulare As New Cellulare
MyCellulare.Colore = "nero"
MyCellulare.SistemaOperativo = "android"
Return MyCellulare
End If
End Function
Can anyone help me to solve this problem???
Thank in advance
greetings
Donato
I think your approach is wrong.
You have simple objects to return, that can be handled easily by the default serializers webapi has to offer.
Your returned object type should be IHttpActionResult (webapi2) or HttpResponseMessage.
I would NOT go for what #Frank Witte suggested, cause returning the object itself is bad practice. Specifically here you can just return a generic object through IHttpActionResult / HttpResponseMessage.
You should do something like:
Public Function GetValue(ByVal id As Integer) As IHttpActionResult
If Id = 1 Then
Dim MyTelevisore As New Televisore
MyTelevisore.Colore = "grigio"
MyTelevisore.Marca = "lg"
Return Ok(MyTelevisore)
Else
Dim MyCellulare As New Cellulare
MyCellulare.Colore = "nero"
MyCellulare.SistemaOperativo = "android"
Return Ok(MyCellulare)
End If
End Function
It throws the error because you do not supply any return type to your GetValue function. You commented that out.
As I can tell from your code you are returning a different type of object depending on the id you supply to the GetValue call. I do not know the complete context of what you are trying to do, but from what I can see it would make more sense to have a different controller, or route at least, for the different types of object:
/api/cellulare/<id>
Would map to a controller CellulareController.
/api/televisore/<id>
Would map to a controller TelevisoreController. Each with their own Get(), Post() and Delete() methods if you will.
Hope this helps.
I'm learning scala and can't find out how to do this:
I'm doing a mapper between scala objects and google appengine entities, so if i have a class like this:
class Student {
var id:Long
var name:String
}
I need to create an instance of that class, in java i would get the Field by it's name and then do field.set(object, value) but I can't find how to do so in scala.
I can't use java reflection since the fields of Student are seen as private and field.set throws an error because of that.
Thanks
Scala turns "var" into a private field, one getter and one setter. So in order to get/set a var by identifying it using a String, you need to use Java reflection to find the getter/setter methods. Below is a code snippet that does that. Please note this code runs under Scala 2.8.0 and handlings of duplicated method names and errors are nonexistent.
class Student {
var id: Long = _
var name: String = _
}
implicit def reflector(ref: AnyRef) = new {
def getV(name: String): Any = ref.getClass.getMethods.find(_.getName == name).get.invoke(ref)
def setV(name: String, value: Any): Unit = ref.getClass.getMethods.find(_.getName == name + "_$eq").get.invoke(ref, value.asInstanceOf[AnyRef])
}
val s = new Student
s.setV("name", "Walter")
println(s.getV("name")) // prints "Walter"
s.setV("id", 1234)
println(s.getV("id")) // prints "1234"