Given this code:
static void Main(string[] args)
{
Expression<Func<SomeDerivedClass, object>> test = i => i.Prop;
var body = (UnaryExpression) test.Body;
Console.WriteLine(((MemberExpression) body.Operand).Member.ReflectedType);
}
public class SomeClass
{
public int Prop { get; private set; }
}
public class SomeDerivedClass : SomeClass
{
}
I would have expected ReflectedType to be SomeDerivedClass given that it is the type of the parameter for the expression. But it is SomeClass, which is - if i understand correctly - the declaring type.
Why is that?
The precise details of how expression trees get built are largely unspecified. The only thing that matters is that the expression tree corresponds to the C# syntax used to build the expression tree. In an ordinary C# expression, there is only the equivalent of DeclaringType, which gets encoded in the IL. The member isn't accessed through reflection at all, so there is no ReflectedType to consider. Because there is no ReflectedType to consider, the two different PropertyInfo objects corresponds equally well to the original source code.
For a potential reason why, consider this somewhat evil derived class:
public class SomeClass
{
public int Prop { get; set; }
}
public class SomeDerivedClass : SomeClass
{
public int get_Prop() { return 4; }
}
Here, the base class's Prop getter is not overridden, but the original get_Prop property compiler-generated getter function is only available through the base class. Therefore, the only correct property getter for Prop is SomeClass.get_Prop. SomeDerivedClass.get_Prop must not be used, even if Prop is accessed on an object statically known to be a SomeDerivedClass.
Combine this with the fact that internally, the C# compiler-generated code to build the expression tree obtains the appropriate PropertyInfo objects by getting the property getter methods, and asking the runtime to find the corresponding PropertyInfo, and you have your answer: the property getter method can only reliably be obtained from SomeClass, therefore you will also get the PropertyInfo from SomeClass.
That's because the expression evaluates to Prop which is defined in SomeClass and not in SomeDerivedClass. Notice that SomeDerivedClass is merely the type of your test lambda parameter, so it has nothing to do with the type of its body, which is an UnaryExpression accessing a property located in SomeClass.
Try also adding Prop to SomeDerivedClass, and you'll get your expected result.
The ReflectedType property retrieves the Type object that was used to obtain this instance of MemberInfo. This may differ from the value of the DeclaringType property if this MemberInfo object represents a member that is inherited from a base class.
http://msdn.microsoft.com/en-us/library/system.reflection.memberinfo.reflectedtype.aspx
Related
I'm trying to write a program that creates a dynamic "Wrapper" class around an existing class with properties, and redirects all the virtual properties getters and setters to a dedicated GetValue and SetValue methods in BaseClass. It's a bit difficult to explain, so here's the code so far:
public abstract class BaseClass
{
protected void SetValue(string propertyName, object value) { ... }
protected object? GetValue(string propertyName) { ... }
}
public class DataClass : BaseClass
{
public virtual string? StrValue { get; set; }
public virtual int IntValue { get; set; }
public virtual bool BoolValue { get; set; }
public virtual List<float>? FloatListValue { get; set; }
}
In this example, my code generates a new class called DataClassWrapper that inherits from DataClass, and overrides all the properties' getter and setter methods with IL code that redirects the call to re respective GetValue and SetValue methods in the base class, passing the property's name as the first argument. The actual method that does all this is a bit too long for this post, but it can be viewed here.
Here's the code that generates the setter for each property: (works correctly in all cases)
setMethodGenerator.Emit(OpCodes.Ldarg_0); // 'this'
setMethodGenerator.Emit(OpCodes.Ldstr, propertyInfo.Name); // 1st argument of SetValue
setMethodGenerator.Emit(OpCodes.Ldarg_1); // value passed into this setter, aka. `value`
setMethodGenerator.Emit(OpCodes.Box, propertyInfo.PropertyType); // cast it to `object`
setMethodGenerator.EmitCall(OpCodes.Call, baseSetterMethod, Type.EmptyTypes); // call SetValue
setMethodGenerator.Emit(OpCodes.Ret); // return
where propertyInfo describes a property from DataClass, and baseSetterMethod references the SetValue() method from the base class.
Getter:
getMethodGenerator.Emit(OpCodes.Ldarg_0); // 'this'
getMethodGenerator.Emit(OpCodes.Ldstr, propertyInfo.Name); // 1st (and only) argument of GetValue
getMethodGenerator.EmitCall(OpCodes.Call, baseGetterMethod, Type.EmptyTypes); // call GetValue
getMethodGenerator.Emit(OpCodes.Castclass, propertyInfo.PropertyType); // cast result to expected type
getMethodGenerator.Emit(OpCodes.Ret); // return it
And some example usage:
var type = CreateDynamicType(typeof(DataClass), baseGetterMethod, baseSetterMethod);
var inst = (DataClass) Activator.CreateInstance(type)!;
inst.IntValue = 1123;
Console.Out.WriteLine(inst.IntValue);
I can read and write the properties StrValue and FloatListValue without any issues, my custom GetValue and SetValue methods are being called as they should be.
However if I try to read a primitive property like BoolValue or IntValue, it returns a seemingly random garbage number (for example -1151033224 the last time I ran this code). If I convert my IntValue into a nullable IntValue? value, it still returns gibberish, but this time the random numbers are much smaller (in the 0-700 range).
The setter method does receive the original int value correctly, and the getter also retrieves it intact, so the problem must be around the generated IL code that calls the getter. But it only seems to happen with primitive types. Does anyone have an idea?
I think your problem is the castclass instruction. The documentation says:
typeTok [the argument] is a metadata token (a typeref, typedef or
typespec), indicating the desired class. If typeTok is a non-nullable
value type or a generic parameter type it is interpreted as “boxed”
typeTok. If typeTok is a nullable type, Nullable, it is interpreted
as “boxed” T.
Unlike coercions (§III.1.6) and conversions (§III.3.27), a cast never changes the actual type of an object and preserves object identity (see Partition I)
That means that if the object is a boxed instance of a value type, castclass does not unbox it but retains the object reference. So this will actually return the managed(!) address of the object, which is useless. In case of a value type, you need to use an unbox.any instruction.
I have two classes, BaseClass and Person. The Person class inherits from BaseClass. I then use the following generic method.
public static PropertyInfo GetProperty<T>(T item, Func<PropertyInfo, bool> predicate)
{
return GetProperty(typeof(T), predicate);
}
Within the BaseClass I have a method, that invokes GetProperty
public class BaseClass
{
public void DoSomething()
{
var property = GetProperty(new Person(), (property) => p.Name == "Name");
}
}
I then call this method from a unit test.
var person = new Person();
person.DoSomething();
When typeof(T) is used, BaseClass is returned. If I use item.GetType() then Person is returned. If I inspect them within the debugger, T is of type BaseClass and item is of type Person. Why does it not infer that T is a typeof(Person), when it already knows that item is a Person?
Edit
My example was wrong above sorry, when I call GetProperty, I pass this.
public class BaseClass
{
public void DoSomething()
{
var property = GetProperty(this, (property) => p.Name == "Name");
}
}
The reason for this inference problem is that generic inference happens at compile time, and is thus identical to specifying the desired type by hand. If you switch to explicitly stating <Person> with the call, does it throw an error during compile?
One way around this is to make sure that the variable (note: NOT the Object!) you pass in is explicitly of the Person class, as it seems to be in your code. Another way is to force generic inference to occur at runtime by using a dyanmic object thusly:
GetProperty(this as dynamic, (prop) => prop.Name == "Name");
By casting this as dynamic it calls GetProperty<dynamic> using the exact type of this at runtime. The problem with this approach is that dynamics are extremely slow compared to other objects.
If your models are strictly a single level of inheritance, you can also utilize Static Polymorphism to handle the generic parameter. Thusly:
public class BaseClass<TSelf> where TSelf : BaseClass<TSelf>
public sealed class Model : BaseClass<Model>
This way you could use TSelf as the parameter in place of T and it would be exactly correct. the problem with this approach is it strictly limits you to a flat single-inheritance hierarchy, as anything inheriting from Model would go back to the original problem and be seen as a Model because it can't override the generic parameter used by its base class.
Assuming your GetProperty function does some reflection to check for a property, you may want to consider passing a Type object in, instead of using a generic and then typeof(T), as .GetType() is far more accurate.
Is there anything to use, to determine if a type is actually a anonymous type? For example an interface, etc?
The goal is to create something like the following...
//defined like...
public static T Get<T>(this IAnonymous obj, string prop) {
return (T)obj.GetType().GetProperty(prop).GetValue(obj, null);
}
//...
//And then used like...
var something = new { name = "John", age = 25 };
int age = something.Get<int>("age");
Or is that just the beauty of an anonymous type? Nothing to identify it self because it takes a new shape?
Note - I realize that you can write an extension method for the object class, but that seems like a little overkill, in my opinion.
EDIT: The list below applies to C# anonymous types. VB.NET has different rules - in particular, it can generate mutable anonymous types (and does by default). Jared has pointed out in the comment that the naming style is different, too. Basically this is all pretty fragile...
You can't identify it in a generic constraint, but:
It will be a class (rather than interface, enum, struct etc)
It will have the CompilerGeneratedAttribute applied to it
It will override Equals, GetHashCode and ToString
It will be in the global namespace
It will not be nested in another type
It will be internal
It will be sealed
It will derive directly from object
It will be generic with as many type parameters as properties. (You can have a non-generic anonymous type, with no properties. It's a bit pointless though.)
Each property will have a type parameter with a name including the property name, and will be of that type parameter, e.g. the Name property becomes a property of type <>_Name
Each property will be public and read-only
For each property there will be a corresponding readonly private field
There will be no other properties or fields
There will be a constructor taking one parameter corresponding to each type parameter, in the same order as the type parameters
Each method and property will have the DebuggerHiddenAttribute applied to it.
The name of the type will start with "<>" and contain "AnonymousType"
Very little of this is guaranteed by the specification, however - so it could all change in the next version of the compiler, or if you use Mono etc.
As I recall, there is a [CompilerGenerated] marker... 2 secs
Plus the name will be freaky, and it will be a generic type ;-p
Actually, for a "get" etc I would probably just use a static (non-extension) method.
If you just want a way to get the value from an instance of an anon-type (at a later point in time), a lambda is probably the best option - note you need a few tricks to pull this off:
static void Main()
{
var foo = new { name = "John", age = 25 };
var func = Get(foo, x => x.age);
var bar = new { name = "Marc", age = 30 };
int age = func(bar);
}
// template here is just for type inference...
static Func<TSource, TValue> Get<TSource, TValue>(
TSource template, Func<TSource, TValue> lambda)
{
return lambda;
}
(edit re the comment) There definitely is this attribute:
var foo = new { A = "B" };
Type type = foo.GetType();
CompilerGeneratedAttribute attrib = (CompilerGeneratedAttribute) Attribute.GetCustomAttribute(
type, typeof(CompilerGeneratedAttribute)); // non-null, therefore is compiler-generated
For the purposes of extension methods there is no way to distinguish an anonymous type. Extension methods work by specifying a method for a compile time nameable type. Anonymous types are un-namable and therefore not visible at compile time. This makes them incompatible with extension methods.
Suppose I have a class named foo, and it has 3 public members foo1, foo2, and foo3.
Now suppose I'm writing a function that takes an instance of class foo as a parameter, but when I'm writing this function I have no idea what public members it has.
Is there a way for me to determine at run-time that it has public members foo1, foo2, foo3 AND ONLY foo1, foo2, foo3. IE - find out what all the public members are?
And can I also determine their types?
Well, that's what Reflection is there for :
Type myObjectType = typeof(foo);
System.Reflection.FieldInfo[] fieldInfo = myObjectType.GetFields();
foreach (System.Reflection.FieldInfo info in fieldInfo)
Console.WriteLine(info.Name); // or whatever you desire to do with it
You could use reflection:
// List all public properties for the given type
PropertyInfo[] properties = foo.GetType().GetProperties();
foreach (var property in properties)
{
string propertyName = property.Name;
}
You should be aware that there could be an additional overhead when using reflection because types are evaluated at runtime.
Have a look at the .net reflection namespace:
http://msdn.microsoft.com/en-us/library/ms173183(VS.80).aspx
This is a job for reflection. Look into methods like:
myFoo.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public);
This will return all public, instance methods that the type has. You can then look through the returned results and determine if this class meets your criteria. There are equivalent methods as well for other types of members, such as GetFields(...), GetProperties(...), etc.
Basically you want to get to know the Type class, which is the core of C#'s reflection capabilities.
foreach(PropertyInfo pi in yourObject.GetType().GetProperties())
{
Type theType = pi.PropertyType;
}
Following article on MSDN should help you determine the methods of a type
Is there anything to use, to determine if a type is actually a anonymous type? For example an interface, etc?
The goal is to create something like the following...
//defined like...
public static T Get<T>(this IAnonymous obj, string prop) {
return (T)obj.GetType().GetProperty(prop).GetValue(obj, null);
}
//...
//And then used like...
var something = new { name = "John", age = 25 };
int age = something.Get<int>("age");
Or is that just the beauty of an anonymous type? Nothing to identify it self because it takes a new shape?
Note - I realize that you can write an extension method for the object class, but that seems like a little overkill, in my opinion.
EDIT: The list below applies to C# anonymous types. VB.NET has different rules - in particular, it can generate mutable anonymous types (and does by default). Jared has pointed out in the comment that the naming style is different, too. Basically this is all pretty fragile...
You can't identify it in a generic constraint, but:
It will be a class (rather than interface, enum, struct etc)
It will have the CompilerGeneratedAttribute applied to it
It will override Equals, GetHashCode and ToString
It will be in the global namespace
It will not be nested in another type
It will be internal
It will be sealed
It will derive directly from object
It will be generic with as many type parameters as properties. (You can have a non-generic anonymous type, with no properties. It's a bit pointless though.)
Each property will have a type parameter with a name including the property name, and will be of that type parameter, e.g. the Name property becomes a property of type <>_Name
Each property will be public and read-only
For each property there will be a corresponding readonly private field
There will be no other properties or fields
There will be a constructor taking one parameter corresponding to each type parameter, in the same order as the type parameters
Each method and property will have the DebuggerHiddenAttribute applied to it.
The name of the type will start with "<>" and contain "AnonymousType"
Very little of this is guaranteed by the specification, however - so it could all change in the next version of the compiler, or if you use Mono etc.
As I recall, there is a [CompilerGenerated] marker... 2 secs
Plus the name will be freaky, and it will be a generic type ;-p
Actually, for a "get" etc I would probably just use a static (non-extension) method.
If you just want a way to get the value from an instance of an anon-type (at a later point in time), a lambda is probably the best option - note you need a few tricks to pull this off:
static void Main()
{
var foo = new { name = "John", age = 25 };
var func = Get(foo, x => x.age);
var bar = new { name = "Marc", age = 30 };
int age = func(bar);
}
// template here is just for type inference...
static Func<TSource, TValue> Get<TSource, TValue>(
TSource template, Func<TSource, TValue> lambda)
{
return lambda;
}
(edit re the comment) There definitely is this attribute:
var foo = new { A = "B" };
Type type = foo.GetType();
CompilerGeneratedAttribute attrib = (CompilerGeneratedAttribute) Attribute.GetCustomAttribute(
type, typeof(CompilerGeneratedAttribute)); // non-null, therefore is compiler-generated
For the purposes of extension methods there is no way to distinguish an anonymous type. Extension methods work by specifying a method for a compile time nameable type. Anonymous types are un-namable and therefore not visible at compile time. This makes them incompatible with extension methods.