Failure to discover property with reflection - reflection

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

Related

How to make a field set-able only inside extension method

Hello i want to be able to set the a of a field of an object only in an extension method. I would want that this field to either be completelely private , or be just get-able from outside:
public class Myclass
{
private int Value{get;set;}
}
public static class Ext
{
public Myclass SetValue(this Myclass obj,int val)
{
this.obj.Value=val;
return obj;
}
}
As you can see in the above example , i have to declare Value public to be able to access it inside the extension , i would be ok with that if i could make the variable only get-ablefrom outside.
I need this functionality because i want to develop something like a fluent api , where you can only set some variables using the extension.
ex:
a=new Myclass();
a.SetValue1(1).SetValue2(2);//--some code //--a.SetValue3(3);
It sounds like you're using the wrong tool for the job, extension methods don't have access non-public members.
The behavior you want is restricted to instance methods or properties. My recommendation is to add an instance method to the class.
If that doesn't persuade you, then you can instead use reflection to update the private instance variable:
public static class Ext
{
public Myclass SetValue(this Myclass obj,int val)
{
var myType = typeof(Myclass);
var myField = myType.GetField("Value", BindingFlags.NonPublic | BindingFlags.Instance);
myField.SetValue(obj, val);
return obj;
}
}
Please note that this has the following gotchas:
There are no compile time checks to save you if you decide to rename the field Value. (though unit tests can protect you)
Reflection is typically much slower than regular instance methods. (though performance may not matter if this method isn't called frequently)
you want it to do it with extension method but you cannot in this case.
Your best option is
public class Myclass
{
public int Value{get; private set;}
public Myclass SetValue(int val)
{
this.Value=val;
return obj;
}
}

How do I get the strongly-typed value of an OutArgument in code?

Given an Activity (created via the designer) that has several OutArgument properties, is it possible to get their strongly-typed value from a property after invoking the workflow?
The code looks like this:
// generated class
public partial class ActivityFoo : System.Activities.Activity....
{
....
public System.Activities.OutArgument<decimal> Bar { ... }
public System.Activities.OutArgument<string> Baz { ... }
}
// my class
var activity = new ActivityFoo();
var result = WorkflowInvoker.Invoke(activity);
decimal d = activity.Bar.Get(?)
string s = activity.Baz.Get(?)
The T Get() method on OutArgument<T> that requires an ActivityContext which I'm not sure how to obtain in code.
I also realize it's possible to get the un-typed values from result["Bar"] and result["Baz"] and cast them, but I'm hoping there's another way.
Updated to make it clear there are multiple Out values, although the question would still apply even if there was only one.
If you look at workflows as code, an Activity is no more than a method that receives input arguments and (potentially) returns output arguments.
It happens that Activities allows one to return multiple output arguments, something that C# methods, for example, don't (actually that's about to change with C# 7 and tuples).
That's why you've an WorkflowInvoker.Invoke() overload which returns a Dictionary<string, object> because the framework obviously doesn't know what\how many\of what type output arguments you have.
Bottom line, the only way for you to do it fully strong-typed is exactly the same way you would be doing on a normal C# method - return one OutArgument of a custom type:
public class ActivityFooOutput
{
public decimal Bar { get; set }
public decimal Baz { get; set; }
}
// generated class
public partial class ActivityFoo : System.Activities.Activity....
{
public System.Activities.OutArgument<ActivityFooOutput> Result { ... }
}
// everything's strongly-typed from here on
var result = WorkflowInvoker.Invoke<ActivityFooOutput>(activity);
decimal d = result.Bar;
string s result.Baz;
Actually, if you don't want to create a custom type for it, you can use said tuples:
// generated
public System.Activities.OutArgument<Tuple<decimal, string>> Result { ... }
// everything's strongly-typed from here on
var result = WorkflowInvoker.Invoke<Tuple<decimal, string>>(activity);
decimal d = result.Item1;
string s result.Item2;
Being the first option obviously more scalable and verbose.

Is there more neat design for requesting static fields in class successors?

I'm implementing network controller that sends requests to the server with integer command type id and binary serialized block of other command data. Prototype of all commands looks like:
class NetCommand {
public static var typeId; // type must be set in successors!
function new() {
}
public function typeGet():Int {
return Reflect.field(Type.getClass(this), "typeId");
}
}
All this mess in typeGet() function done just for access to the static variables with type ids of all successors. I can't simply write
return typeId;
because statics are not inheritable and this method will return 0 as a value of prototype's variable. Is there any neat solution? Is my solution cross-platform?
Update:
All command classes must be registered in controller class like this:
public function bindResponse(aClass:Class<NetCommand>) {
var typeId = Reflect.field(aClass, "typeId");
mBindResponse.set(typeId, aClass);
}
and then when new command arrives its data passes to the method that find necessary class by command id, creates instance of desired class and passes other data to it:
function onResponse(aTypeId:Int, aData:Dynamic) {
var cmdClass:Class<NetCommand> = mBindResponse.get(aTypeId);
var command:NetCommand = Type.createInstance(cmdClass, []);
command.response(aData); // this must be overriden in successor classes
}
Method typeGet() is used only for targeting outgoing instances and error handling with default behaviour of error command class without creating a heap of classes that differs only by typeId constant. So this method suppreses implementation of the real command id and may be overriden for example.
Why don't you simply make typeId an instance member (not static) ?

Scala: set a field value reflectively from field name

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"

To mock an object, does it have to be either implementing an interface or marked virtual?

or can the class be implementing an abstract class also?
To mock a type, it must either be an interface (this is also called being pure virtual) or have virtual members (abstract members are also virtual).
By this definition, you can mock everything which is virtual.
Essentially, dynamic mocks don't do anything you couldn't do by hand.
Let's say you are programming against an interface such as this one:
public interface IMyInterface
{
string Foo(string s);
}
You could manually create a test-specific implementation of IMyInterface that ignores the input parameter and always returns the same output:
public class MyClass : IMyInterface
{
public string Foo(string s)
{
return "Bar";
}
}
However, that becomes repetitive really fast if you want to test how the consumer responds to different return values, so instead of coding up your Test Doubles by hand, you can have a framework dynamically create them for you.
Imagine that dynamic mocks really write code similar to the MyClass implementation above (they don't actually write the code, they dynamically emit the types, but it's an accurate enough analogy).
Here's how you could define the same behavior as MyClass with Moq:
var mock = new Mock<IMyInterface>();
mock.Setup(x => x.Foo(It.IsAny<string>())).Returns("Bar");
In both cases, the construcor of the created class will be called when the object is created. As an interface has no constructor, this will normally be the default constructor (of MyClass and the dynamically emitted class, respectively).
You can do the same with concrete types such as this one:
public class MyBase
{
public virtual string Ploeh()
{
return "Fnaah";
}
}
By hand, you would be able to derive from MyBase and override the Ploeh method because it's virtual:
public class TestSpecificChild : MyBase
{
public override string Ploeh()
{
return "Ndøh";
}
}
A dynamic mock library can do the same, and the same is true for abstract methods.
However, you can't write code that overrides a non-virtual or internal member, and neither can dynamic mocks. They can only do what you can do by hand.
Caveat: The above description is true for most dynamic mocks with the exception of TypeMock, which is different and... scary.
From Stephen Walther's blog:
You can use Moq to create mocks from both interfaces and existing classes. There are some requirements on the classes. The class can’t be sealed. Furthermore, the method being mocked must be marked as virtual. You cannot mock static methods (use the adaptor pattern to mock a static method).

Resources