Is there a way to use ParameterInfo and PropertyInfo Interchangeably? - c#

To me they are very similar structures. I was hoping there was a way to cast or convert one to the other easily.
I'm using reflection to do some magic. I've chosen the path to use parametrized constructors to create some user selected objects which they fill in values for the parameters using a UI.
The problem is one of the objects takes in a structure as a param and I can't get at the structures properties as parameter infos just property infos.
But I don't want to just reproduce the parameter info code I have now for property infos. It be nice if I could pass in a property info as a parameter info. Everything is really similar except for some names of some properties; ParameterType as opposed to PropertyType and what not.
I may have to do my own conversion or write my own class that houses the properties that I need and just use that custom object instead. Cheers.

No, there is not.
Those two classes represent two very different concepts.
A property is an attribute on an Type. The PropertyInfo class will allow you to set or get the value and will tell you additional information about the Property.
A parameter is an attribute of a method signature (an accessor on a type can have a parameter as well). The ParameterInfo class represents this concept and can tell you the Type of the parameter, the position in the method signature, whether it is an out or ref parameter, etc. See: MSDN doc. A ParameterInfo is not directly associated to a Type.

Related

Using nameof for a recursive generic type's property

I have the following class
public abstract class Result<TResult, TData> where TResult : Result<TResult, TData>
{
public virtual TData Data { get; private set; }
}
How can I use nameof on the Data property?
It tried some options but got compilation errors
nameof(Result<object, object>.Data)
Error CS0311
The type 'object' cannot be used as type parameter 'TResult' in the generic type or method
'Result<TResult, TData>'. There is no implicit reference conversion from 'object' to
'Result<object, object>'
UPDATE
To better specify:
I did not write the class in the first snippet, but I have to use it as it is.
I need to use reflection to get a PropertyInfo instance for the Data property. I can do it by calling GetProperty("Data"), but I prefer to avoid strings in case the name property is renamed with the Visual Studio Refactoring (for example from Data to Content).
I cannot use nameof(Data) and I am in a different context that doesn't know about the Data property in that class.
As such, I would call GetProperty(nameof({whatever}.Data)). Of course, if not possible I would use the string. But if there is a way, I would like to know it.
Unfortunately, the nameof operator does not work with unbound generic types. E.g. you'd like to be able to write nameof(Result<,>.Data), just like you can today write something like typeof(Result<,>). So you would need to specify type parameters when trying to get the nameof(Result<TResult, TData>.Data) value.
Which you've tried, but you provided object as the type parameter for both parameters, even though your generic type constrains TResult as being derived from Result<TResult, TData>. The type object doesn't meet the constraint, so that can't possibly work. Hence the compiler error.
Obviously, if you can provide any type that does meet the constraint, that would solve the compiler error and allow you to use the nameof operator. There's not enough information in your question to know whether that's an option in your specific scenario.
I agree with this comment that you would probably be better off asking a different question, one which takes a step back and explains how you arrived at feeling you needed this syntax in the first place. It's not clear what the broader goal you're trying to accomplish is, where you don't have known type parameters to use for this expression. Typically, code outside of the generic type that wants to make use of the generic type, would actually know the type parameters it intends to use with the generic type.
Note that in the context of the generic type itself, you can refer to the property without knowing the exact type parameters, since the property identifier does not need qualification. E.g. nameof(Data) would work, for any code that's actually in the generic class Result<TResult, TData>. Whether that helps in your specific scenario is unclear from the information provided so far.

What is System.Reflection.RuntimePropertyInfo and how do I compare it?

I was suprised to see that the actual type of the object I get with x.GetType().GetProperty("Foo") is not System.Reflection.PropertyInfo but System.Reflection.RuntimePropertyInfo.
I don't see this type documentation in msdn or elsewhere.
My actual problem grows from reference-comparing two properties. I receive a property from third-party lib and compare it with a property which I get with .GetProperty("Foo") on the same type. I expected properties to be the same object (and they looks like the same property in "Locals" window while debugging), but they are not (GetHashCode result is different). So, I think it can somehow be related with the actual type of the property object which is System.Reflection.RuntimePropertyInfo.
What is System.Reflection.RuntimePropertyInfo? How to compare it? Does it behaves the same as usual PropertyInfo?
RuntimePropertyInfo is an internal implementation. It is a PropertyInfo, and in fact, GetProperty returns PropertyInfo (even if the underlying type is RuntimePropertyInfo).
The third-party lib is probably getting the property of a different type than you are?
new blah().GetType().GetProperty("Test") == new blah().GetType().GetProperty("Test")
Returns true.
PropertyInfo is an abstract class while RuntimePropertyInfo is the concrete implementation of PropertyInfo.
When we call Type.GetProperties() or Type.GetProperty() they actually returns the RuntimePropertyInfo.
The reason you are getting reference not equal could be because of the Type signature difference in the third-party lib.

Access <AnonymousType> fields

I have an AnonymousType object that contacts two fields with their values. How can I access the value of these fields?
Ex:
SourceTypeObject { Source_Type_Id = 1, Source_Type_Name = "bibliography" }
I need to do something like : SourceTypeObject.Source_Type_Id
Is that possible?
EDIT:
Here's what I get if I tried to access the property directly:
Yes, this is the exact purpose of anonymous types. The only thing that might prevent you from doing so is if you passed the anonymous type around as a parameter with type "object". This would hide information about the anonymous type, and it would look like just any old object then.
The only recourse if this is the case is to use reflection, which is slow and awkward. Anonymous types are a meant to be a very "local" phenomenon, and if you find yourself wanting to use them elsewhere in the program, it's worth the time to promote it to a real type.
EDIT: In response to the image you posted, assuming the array is declared locally just outside of view, try to replace the object SourceTypeObject with var SourceTypeObject. This allows it to infer the anonymous type instead of being told that it's an object.

How to create a value type or string type object at runtime using Reflection

Probably simple but could not figure out. I am loading an assembly at runtime and browsing through some classes and generating input controls for its properties. To create an instance of an object at runtime I am using:
object o = PropertyType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, Type.EmptyTypes,null).Invoke(null);
and it works fine for class types. When the type is an array, I use
object o = PropertyType.Type.GetConstructor(new Type[] { typeof(int) }).Invoke(new object[] { 0 });
which also works fine. But when it comes to string type or value types GetConstructor.Invoke does not work. I also tried Activator.CreateInstance which also did not work.
What you're running into is that value types don't really have parameterless constructors. C# makes it look like they do, but they don't at the CLR level.
Activator.CreateInstance should work fine for real value types though:
object o = Activator.CreateInstance(typeof(int));
Console.WriteLine(o); // Prints 0
This will always give the default value for any value type.
Now, you're asking about strings - what string would you expect to create? The default value for the string type is null - but would you want the empty string instead? If so, you'll need to special-case that code.
If you want to be able to instantiate arbitrary objects with particular values, one thing you can check is if there is a TypeConverter that supports converting an instance (with the value you want to match) to an InstanceDescriptor. I'm not entirely sure what you're doing (your example suggests you're trying to create 'default' instances of the different objects), but just thought I'd mention this in case it's relevant. I use this in Emit code to emit arbitrary constant values to the stack via IL. Here's the snippet that gets the InstanceDescriptor:
var converter = TypeDescriptor.GetConverter(value);
if (converter.CanConvertTo(typeof (InstanceDescriptor)))
{
var desc = (InstanceDescriptor) converter.ConvertTo(value, typeof (InstanceDescriptor));
}
The descriptor specifies a means of constructing the instance, which could be calling a constructor, calling a static method, accessing a static property or accessing a static field. It also specifies whether the construction completely sets the value of the type to match your original instance; if not, you'll need to do additional reflection and setting of properties.
This is the mechanism that the WinForms Designer uses when generating the code-behind for the controls on the form, so it is supported for the common types that show up as properties of controls accessible from the designer.
The int type doesn't have any constructors.
The code you write is going to depend on the property's type; normally, you'd write special-case code for string, int and other primitive types.
Your code above contains the literal 0; how do you decide what values to pass to the constructors?

Getting information about a member invoked using Type.InvokeMember()

I'm using Type.InvokeMember() to dynamically invoke various members of a Type. Since the members can be generic and also include out parameters etc., I'm happy to have the runtime handle this. However, I also need to have additional information about the actual member that's been invoked -- particularly, the return type. If this type is nullable, I need to do some additional processing.
So, I'd like to know if it's possible to get the MemberInfo object corresponding to the member that was invoked through Type.InvokeMember().
Alternatively, is there a variant of InvokeMember() that simply does the lookup and returns the appropriate MemberInfo object but doesn't actually invoke it? I can then analyze the MemberInfo object, and later invoke it directly.
I haven't been able to find any .NET APIs that do this, so I suspect I'll need to handcode it. Let me know if I'm missing something.
Alternatively, is there a variant of InvokeMember() that simply does the lookup and returns the appropriate MemberInfo object
You can use the Type.GetMethod method, giving a description of the desired method (name and parameter types). It returns a MethodInfo object which includes the return type.
typeof(yourType).GetMethod(...);

Categories

Resources