mercredi 1 juin 2016

Calling `Contains` method from C# dynamic type yields error - why?

I simplified my problem into a tiny program which examples the exact error I receive during run-time.

You can copy-paste it into a console application and see for yourself.

using System.Collections.Generic;

namespace ConsoleApplication5
{
    class Program
    {
        static void Main(string[] args)
        {
            var list = new List<MyDataClass>()
            {
                new MyDataClass {A = 1, B = 1},
                new MyDataClass {A = 3, B = 8}
            };
            var ops = new MyOperationsClass();
            ops.ReallyGreatOperation(list, list[0]);
        }
    }

    public class MyDataClass
    {
        public int A { get; set; }
        public int B { get; set; }

        public void AddDataPartsToEachOther()
        {
            var c = A + B;
            A = c;
            B = c;
        }
    }

    public class MyOperationsClass
    {
        public void ReallyGreatOperation(object obj, object z)
        {
            dynamic x = obj;
            if (x.Contains(z)) //<-- gets an error here..
                ((dynamic)z).AddDataPartsToEachOther();
        }
    }
}

So what is really the problem?

As I understand dynamic keyword can be used as a wildcard, if a method exists it will be called with no problem. so why is it not working for me in this scenario?

Now, I know that I can change it to work by doing this:

public class MyOperationsClass
{
    public void ReallyGreatOperation(object obj, object z)
    {
        dynamic x = obj;
    //    if (x.Contains(z)) //<-- gets an error here..
    //        ((dynamic)z).AddDataPartsToEachOther();
        if (x.GetType().GetMethod("Contains").Invoke(obj, new[] {z}))
            ((dynamic)z).AddDataPartsToEachOther();
    }
}

But as I said - what I wish is to understand why the more "natural" way is not working.. cause if I do it the 2nd way out of no choice - I don't see the point of dynamic in the language anymore.

The actual error received:

An unhandled exception of type 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in System.Core.dll

Additional information: The best overloaded method match for 'System.Collections.Generic.List.Contains(ConsoleApplication5.MyDataClass)' has some invalid arguments

Thanks.





Casting Number to double primitive [duplicate]

This question already has an answer here:

I'm trying to access a HashMap<String, Number> via reflection:

Serializable obj; //here goes the HashMap
String name;
...
return (double)obj.getClass().getDeclaredMethod("get", Object.class).invoke(obj, name);

but so far all I got is a casting error caused by the line above:

java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Double

Indeed, the map value that was accessed by the key name was Integer.So I've changed the line to:

return obj.getClass().getDeclaredMethod("get", Number.class).invoke(obj, name).doubleValue();

but that didn't work out either. I even got doubleValue() underlined as "undefined for the type Object" (but why Object if I have Number.class?).

I'm not sure what casting rules I'm breaking. Can someone, please, help me if my map entries have various number values (Integer, Float, Double) but I need the method to return a double value (primitive).





Swift: NSClassFromString from dependencies

I'm having this problem getting the reflection to work from external frameworks as dependencies.

So let say I had two projects, one is a sample app project

SampleApp.xcodeproj
@obj protocol Extension : NSObjectProtocol {
    //..Some definitions
}

And another with the framework project that the sample app will be depended on and is a submodule of the sample app project.

Framework.xcodeproj
class SampleClass : NSObject, Extension {
   //some definitions
}

In this framework, Extension.swift file, where the Extension protocol is defined, is included in the build as a reference

Now here's the problem on this code

if let customExtension = NSClassFromString("Framework.SampleClass") as? NSObject.Type {
    let extensionInstance = customExtension.init()
    if extensionInstance is Extension { //The problem here, it returned false at this point
        print("It is an Extension")
    } else {
        print("It is not an Extension")
    }
}

I noticed that the Extension protocol defined in the Framework project was defined as Framework.Extension instead of SampleApp.Extension. How would I make it so the SampleClass class is defined as SampleApp.Extension instead of Framework.Extension?





Using a Class

This question already has an answer here:

I'm trying to use reflection to get a list of classes implementing an abstract class, Detector. I would like to use the elements of this list (of type Class<T extends Detector>) as a type parameter for another class, DetectorWrapper<T extends Detector>, so that I can easily instantiate T within that class (i.e., using new T(...)). Is it possible to use reflection for this, or should I instead pass Class<T> to DetectorWrapper and use reflection to invoke the constructor whenever I need an instance of T?





Creating a method in a class created with Reflection in C#

I am creating a type with reflection by using the code from this answer. And I want to add a function to this class (probably using ILGenerator). And in the comment section of this answer, Sergey Mirvoda commented that ILGenerator emit commands can be obtained by simply following these steps: compile it into assembly and open with reflector, switch to IL view and you will see code that copypastable

I am using VS Ultimate 2013. Is there a way to do this with VS? Or do I need to use third party apps?





How to emit default(TimeSpan) as the default value of an optional parameter

I want to emit dynamic method which is exactly the same as below:

void Foo(TimeSpan ts = default(TimeSpan))

By using ildasm, i can see it has been complied as nullref.

However from what i can get, if i want to achieve the same by Emit code, the method i can call named ParameterBuilder.SetConstant, and it will throw exception when the optional value type is TimeSpan.

I even decompiled SetConstant method, it handles DateTime explicitly(but not TimeSpan). Nullref is also not acceptable. From that code, it seems there's no way to set default(TimeSpan) as a default value.

Can anyone help?





Reflection - getInterfaces() shows weird interfaces

Using Hibernate, I get a List<BlablaPO> (BlablaPO implements Blabla). When I do something like this:

for(Blabla blabla : list) {
    Class<?>[] interfazes = blabla.getClass().getInterfaces();
}

This code is just a part of a piece of code that accepts a Collection<T>. Today, I used this code again on a new List<Blabla>, my returned interfaces do no have Blabla in them, instead I get 2 interfaces:

  • interface org.hibernate.proxy.HibernateProxy
  • interface javassist.util.proxy.ProxyObject

Am I loading the collection wrongly? I tried loading the collection eagerly.