Is there a way to use either System.CodeDom or the Roslyn API to resolve an overloaded method call from code? At runtime, I have a method name and a list of parameters, I want to find the method the compiler would have picked at compile time.
As #SLaks and #just.another.programmer suggested it is possible to exploit C# dynamic infrastructure. But it's really not straightforward nor simple. I was gazing into decompiled code for couple of hours to find following magic code. And I don't understand it completely. In the first step Binder class is created, with parameter options set to use compile time types.
In the second magic step, the binder is called with the actual parameters. Each parameter has its value (null, its not used when UseCompileTimeType is set) and their expression. If you know types instead of expression, use Expression.Parameter(yourType) to substitute them.
public static Expression GetInvokeMemberExpression(Expression expr, string name, Expression[] arguments)
{
var type = expr.Type;
var argTypes = arguments.Select(e => e.Type).ToArray();
// do magic #1
var binder = (DynamicMetaObjectBinder)Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember(
CSharpBinderFlags.None, name,
Type.EmptyTypes, // type arguments
typeof(object),
Enumerable.Repeat(0, argTypes.Length + 1).Select(_ => CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null)).ToArray());
// do magic #2
var result = binder.Bind(DynamicMetaObject.Create(null, expr), arguments.Select(a => DynamicMetaObject.Create(null, a)).ToArray());
var resultMethodCall = (result.Expression as UnaryExpression).Operand as MethodCallExpression; // unwrap convert to ebject expression
var method = resultMethodCall.Method;
return resultMethodCall;
}
I was trying similar piece of code in DotVVM framework, but I haven't found a way how to "inject" custom implicit conversions, so I wrote a simple method overload recognition function. But we are still using dynamic for operators. You can find the code on github
Related
I have an interface defined in C# that implements IEnumerable. The implementation of the interface will be done in C++/WinRT as it needs direct access to native code. When I attempt to implement this interface using C++/WinRT, the generated header/implementation contains two 'First()' functions (one from IIterable, and one from IBindableIterable) with different return types. Obviously this isn't going to compile.
Is there some way to "rename" one (or both) of the conflicting functions in the IDL file? C++/CX had a work around that allowed you to use a different function name and then 'bind' it back to the interface name.
Simplified example code below:
Interface:
public interface IUInt32Array : IEnumerable<uint> {}
IDL:
[default_interface]
runtimeclass UInt32Array : IUInt32Array
{
UInt32Array(UInt32 size);
}
IDL Generated Header:
struct UInt32Array : UInt32ArrayT<UInt32Array>
{
UInt32Array(uint32_t size);
Windows::Foundation::Collections::IIterator<uint32_t> First(); // <-- Problem
Windows::UI::Xaml::Interop::IBindableIterator First(); // <-- Problem
}
A solution for this specific problem is to use a combination of 'auto' as the declared return type for the First() function implementation, and to return a type with conversion operators for the two different return types.
Here is an example showing how this was solved in the CppWinRT source code. The linked source code is for the base_collections_vector.h header, specifically see the convertible_observable_vector::First() function (replicated below).
auto First() {
struct result {
container_type* container;
operator wfc::IIterator<T>() {
return static_cast<base_type*>(container)->First();
}
operator wfc::IIterator<Windows::Foundation::IInspectable>() {
return make<iterator>(container);
}
};
return result{ this };
}
Notice here that the function itself is defined as returning auto, which allows us to return an intermediate type. This intermediate type then implements conversion operators for converting to the type expected by the caller. This works for this particular problem as the generated CppWinRT source code immediately assigns the result of the call to a value of the expected type, thus immediately causing the invocation of the conversion operators which in turn return the final correct iterator type.
Thanks to Kenny Kerr who pointed me at both the example and a write-up explaining the above.
How can I pass property getter to a function that accepts function type?
Here is an example of what I want achieve:
class Test {
val test: String
get() = "lol"
fun testFun(func: ()->String) {
// invoke it here
}
fun callTest() {
testFun(test::get)
// error: Type mismatch: inferred type is
// KFunction1<#ParameterName Int, Char> but () -> String was expected
}
}
Is there a way?
You can reference the getter by writing ::test (or this::test).
When you write test::get, you are actually referencing the get method on String. That method takes an index and returns the character at that index.
If the property was a var and you want a reference to its setter, you can write ::test::set.
For more info on property references, see here: https://kotlinlang.org/docs/reference/reflection.html#bound-function-and-property-references-since-11
As already mentioned, you can use this::test to refer to the getter. Alternatively, if you have kotlin-reflect, you can do this::test.getter.
When you pass the field as a function, it assumes you mean the getter. As a result, if you want the setter, you have two options:
this::test::set
or
this::test.setter
The latter, just like this::test.getter requires kotlin-reflect, or the program will crash (tested locally with Kotlin 1.2.50)
You can, however, get the getter in another way. But I recommend you just stick with this::test because it's shorter.
You can do:
this::something::get
With just something::get it refers to the method inside the String class, which returns a char at an index. For reference, the method declaration:
public override fun get(index: Int): Char
If you don't mind, just use { test } (e.g. testFun { test }). This will exactly translate to your () -> String. The next best alternative is probably ::test (or this::test) as was already mentioned.
The second has probably only minor (negligible?) impact on performance. I did not test it myself, nor did I found any source which tells something regarding it. The reason why I say this, is how the byte code underneath looks like. Just due to this question I asked myself about the difference of the two: Is the property reference (::test) equivalent to a function accessing the property ({ test }) when passed as argument e.g. `() -> String`?
It seems that you are doing something wrong on logical level.
If you are overriding get method of a variable, then you can access it's value through this get method. Thus, why bother with test::get (which is totally different method, by the way, all you are doing is trying to access char from string), when you can just access variable by it's name?
I have a problem while using jmockit for the following scenario. Did a research on the web, but couldn't locate the answers yet.
In the record phase, I am setting the expectation on an object that is partially mocked. While doing it, I would like to mock a private method with single parameter. But i don't really concerned with that parameter value. I want to match all invocation of that particular private method with any instance of argument passed to it. How do I do it in Jmockit. Is there a way?
new Expectations(student) {
{
Deencapsulation.invoke(student, "setDepartment", (Department) any);
result = new Delegate<Student>() {
public void setDepartment(Department dept) {
System.out.println("Mocked setDepartment() methodd.....");
}
};
}
};
In the above code, (Department) any can not be passed, since Deencapsulation.invoke(...) method doesn't accept null value.
Note the API documentation for the any field says:
"In invocations to non-accessible methods or constructors (for example, with Deencapsulation.invoke(Object, String, Object...)), use withAny(T) instead."
That is, you need to use withAny(Department.class) with the invoke(...) call.
As of JMockit v1.49, I use:
withInstanceOf(Department.class)
It works as expected.
I'm trying to develop my own editable data grid for MVC in a fluent interface usable in a View. My question is really about using lambdas, not about data grids, but the context might help for understanding my question. Anyway, I have some code that looks like this:
#model IEnumerable<AdamOneilSoftware.Models.Something>
#{
var firstItem = Model.FirstOrDefault();
}
#(Html.DataGrid(Model)
.CssClass("data")
.TextBox(model => firstItem.Text)
.TextBox(model => firstItem.Position)
.Render())
This much compiles okay. You can see that I want to use lambdas to setting up columns of my data grid. The thing I don't understand is how to do anything with those lambdas in my data grid class. I have surmised that I need to compile/invoke the expression, but I'm stuck on the Invoke part. Here's what I have:
public DataGridBuilder<TModel> TextBox<TValue>(Expression<Func<TModel, TValue>> expression)
{
var del = expression.Compile();
// invoke the delegate?
var result = del.Invoke(); // but this expects a TModel argument
return this;
}
The Invoke call expects a TModel argument (according to the Func declaration -- I understand that). But this doesn't work--and rightly so:
var result = del.Invoke(TModel);
How do I form the TModel argument in the Invoke call? Or am I heading the wrong direction completely? The goal is to do something like what the DisplayFor and EditorFor methods do--render some HTML with some awareness of the target property's metadata (DataFormatString, Display label, and so on).
You need to get the view's Model instance to pass as the parameter.
You can find that in Html.ViewData.Model.
I have a Serialization interface which is designed to encapsulate the differences between XML/JSON/binary serialization for my application. It looks something like this:
interface Serialization {
bool isObject();
int opApply(int delegate(string member, Serialization value) del); //iterate object
...
int toInt(); //this part is ugly, but without template member overloading, I
long toLong(); //figure out any way to apply generics here, so all basic types
... //have a toType primitive
string toString();
}
class JSONSerialization : Serialization {
private JSON json;
...
long toLong() {
enforce(json.type == JSON_TYPE.NUMBER, SerializationException.IncorrectType);
return cast(long)json.toNumber();
}
...
}
So, what I then set up is a set of templates for registering type deserializers and calling them:
...
registerTypeDeserializer!Vec3(delegate Vec3(Serialization s) {
return Vec3(s[0].toFloat, s[1].toFloat, s[2].toFloat);
});
...
auto v = parseJSON("some file").deserialize!Vec3;
...
registerTypeDeserializer!Light(delegate Light(Serialization s) {
return new Light(s["intensity"].toFloat, s["position"].deserialize!Vec3);
});
This works well for structs and simple classes, and with the new parameter identifier tuple and parameter default value tuple I should even be able to add automatic deserializer generation. However, I don't really like the inconsistency between basic and user defined types, and more importantly, complex types have to rely on global state to acquire references:
static MaterialLibrary materials;
registerTypeDeserializer!Model(delegate Model(Serialization s) {
return new Model(materials.borrow(s["material"].toString), ...);
});
That's where it really falls apart. Because I can't (without a proliferation of register deserializer functions) pass other parameters to the deserializer, I'm having difficulty avoiding ugly global factories. I've thought about eliminating the deserialize template, and requiring a deserialize function (which could accept multiple parameters) for each user defined type, but that seems like a lot of work for e.g. POD structs.
So, how can I simplify this design, and hopefully avoid tons of boilerplate deserializers, while still allowing me to inject object factories appropriately, instead of assigning them globally?
Basic types can be read using readf \ formattedRead, so you can create a wrapper function that uses this formattedRead it possible, otherwise it uses a static function from the desired type to read the value. Something like this:
auto _readFrom(T)(string s){
static if(__traits(compiles,(readf("",cast(T*)(null))))){
T result;
formattedRead(s,"%s",&result);
return result;
}else{
return T.readFrom(s);
}
}