How set property name/value dynamically? - c#

Hi I'm not sure if I'm describing it properly, but based on a list of strings, I want to set the values of properties that belong to an object (all properties, which are objects, that match the string names):
var _parentObject = _parentObjectService.GetParentObject(viewModel.Id);
var _listOfPropertyNames = GetPropertyNames();
foreach (var item in _listOfPropertyNames)
{
// Pseudo code, I know it's gibberish:
_parentObject.Tests.[item] = viewModel.Tests.[item];
}
Hopefully that makes sense, please let me know if not.
Thank you.

It sounds like you're looking for AutoMapper, which will do all this for you:
//Once:
Mapper.CreateMap<FromType, ToType>();
//Then:
Mapper.Map(viewModel.Tests, _parentObject.Tests);
If you want to do it yourself, you'll need reflection (slow) or compiled expression trees (fast).

Use reflection to set the property value, as per: Set object property using reflection
Really simple example:
void SetParamByName(object obj, string paramName, object value)
{
obj.GetType()
.InvokeMember(
paramName,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty,
Type.DefaultBinder,
obj,
value
);
}

Related

how to call a private method from dll? [duplicate]

There are a group of private methods in my class, and I need to call one dynamically based on an input value. Both the invoking code and the target methods are in the same instance. The code looks like this:
MethodInfo dynMethod = this.GetType().GetMethod("Draw_" + itemType);
dynMethod.Invoke(this, new object[] { methodParams });
In this case, GetMethod() will not return private methods. What BindingFlags do I need to supply to GetMethod() so that it can locate private methods?
Simply change your code to use the overloaded version of GetMethod that accepts BindingFlags:
MethodInfo dynMethod = this.GetType().GetMethod("Draw_" + itemType,
BindingFlags.NonPublic | BindingFlags.Instance);
dynMethod.Invoke(this, new object[] { methodParams });
Here's the BindingFlags enumeration documentation.
BindingFlags.NonPublic will not return any results by itself. As it turns out, combining it with BindingFlags.Instance does the trick.
MethodInfo dynMethod = this.GetType().GetMethod("Draw_" + itemType,
BindingFlags.NonPublic | BindingFlags.Instance);
And if you really want to get yourself in trouble, make it easier to execute by writing an extension method:
static class AccessExtensions
{
public static object call(this object o, string methodName, params object[] args)
{
var mi = o.GetType ().GetMethod (methodName, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance );
if (mi != null) {
return mi.Invoke (o, args);
}
return null;
}
}
And usage:
class Counter
{
public int count { get; private set; }
void incr(int value) { count += value; }
}
[Test]
public void making_questionable_life_choices()
{
Counter c = new Counter ();
c.call ("incr", 2); // "incr" is private !
c.call ("incr", 3);
Assert.AreEqual (5, c.count);
}
Microsoft recently modified the reflection API rendering most of these answers obsolete. The following should work on modern platforms (including Xamarin.Forms and UWP):
obj.GetType().GetTypeInfo().GetDeclaredMethod("MethodName").Invoke(obj, yourArgsHere);
Or as an extension method:
public static object InvokeMethod<T>(this T obj, string methodName, params object[] args)
{
var type = typeof(T);
var method = type.GetTypeInfo().GetDeclaredMethod(methodName);
return method.Invoke(obj, args);
}
Note:
If the desired method is in a superclass of obj the T generic must be explicitly set to the type of the superclass.
If the method is asynchronous you can use await (Task) obj.InvokeMethod(…).
Reflection especially on private members is wrong
Reflection breaks type safety. You can try to invoke a method that doesn't exists (anymore), or with the wrong parameters, or with too much parameters, or not enough... or even in the wrong order (this one my favourite :) ). By the way return type could change as well.
Reflection is slow.
Private members reflection breaks encapsulation principle and thus exposing your code to the following :
Increase complexity of your code because it has to handle the inner behavior of the classes. What is hidden should remain hidden.
Makes your code easy to break as it will compile but won't run if the method changed its name.
Makes the private code easy to break because if it is private it is not intended to be called that way. Maybe the private method expects some inner state before being called.
What if I must do it anyway ?
There are so cases, when you depend on a third party or you need some api not exposed, you have to do some reflection. Some also use it to test some classes they own but that they don't want to change the interface to give access to the inner members just for tests.
If you do it, do it right
Mitigate the easy to break:
To mitigate the easy to break issue, the best is to detect any potential break by testing in unit tests that would run in a continuous integration build or such. Of course, it means you always use the same assembly (which contains the private members). If you use a dynamic load and reflection, you like play with fire, but you can always catch the Exception that the call may produce.
Mitigate the slowness of reflection:
In the recent versions of .Net Framework, CreateDelegate beat by a factor 50 the MethodInfo invoke:
// The following should be done once since this does some reflection
var method = this.GetType().GetMethod("Draw_" + itemType,
BindingFlags.NonPublic | BindingFlags.Instance);
// Here we create a Func that targets the instance of type which has the
// Draw_ItemType method
var draw = (Func<TInput, Output[]>)_method.CreateDelegate(
typeof(Func<TInput, TOutput[]>), this);
draw calls will be around 50x faster than MethodInfo.Invoke
use draw as a standard Func like that:
var res = draw(methodParams);
Check this post of mine to see benchmark on different method invocations
Are you absolutely sure this can't be done through inheritance? Reflection is the very last thing you should look at when solving a problem, it makes refactoring, understanding your code, and any automated analysis more difficult.
It looks like you should just have a DrawItem1, DrawItem2, etc class that override your dynMethod.
Invokes any method despite its protection level on object instance. Enjoy!
public static object InvokeMethod(object obj, string methodName, params object[] methodParams)
{
var methodParamTypes = methodParams?.Select(p => p.GetType()).ToArray() ?? new Type[] { };
var bindingFlags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static;
MethodInfo method = null;
var type = obj.GetType();
while (method == null && type != null)
{
method = type.GetMethod(methodName, bindingFlags, Type.DefaultBinder, methodParamTypes, null);
type = type.BaseType;
}
return method?.Invoke(obj, methodParams);
}
I think you can pass it BindingFlags.NonPublic where it is the GetMethod method.
Could you not just have a different Draw method for each type that you want to Draw? Then call the overloaded Draw method passing in the object of type itemType to be drawn.
Your question does not make it clear whether itemType genuinely refers to objects of differing types.
It should be noted that calling from a derived class can be problematic.
Error prone:
this.GetType().GetMethod("PrivateTestMethod", BindingFlags.Instance | BindingFlags.NonPublic)
Correct:
typeof(CurrentClass).GetMethod("PrivateTestMethod", BindingFlags.Instance | BindingFlags.NonPublic)
Read this (supplementary) answer (that is sometimes the answer) to understand where this is going and why some people in this thread complain that "it is still not working"
I wrote exactly same code as one of the answers here. But I still had an issue. I placed break point on
var mi = o.GetType().GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance );
It executed but mi == null
And it continued behavior like this until I did "re-build" on all projects involved. I was unit testing one assembly while the reflection method was sitting in third assembly. It was totally confusing but I used Immediate Window to discover methods and I found that a private method I tried to unit test had old name (I renamed it). This told me that old assembly or PDB is still out there even if unit test project builds - for some reason project it tests didn't built. "rebuild" worked

Looping though a dictionary containing objects

I have the following loop over a dictionary type collection
foreach(KeyValuePair<Vector2, Object> entry in v_map.map_set)
{
}
I want to access the object properties, but the expected syntax doesn't work. E.G:
foreach(KeyValuePair<Vector2, Object> entry in v_map.map_set)
{
Object ob = entry.Value;
ob.property;
}
Fails because C# can't find the property wanted.
So, how do I access the desired properties?
solution:
foreach(KeyValuePair<Vector2, Object> entry in v_map.map_set)
{
if (entry.Value is warehouse)
{
warehouse ob = (warehouse)entry.Value;
}
}
If you know the type of the objects that are in the KeyValuePair, you can cast it to that type, and you will be able to find the properties you need.
And if you have several different objects stored, you can check which type it is by using is.
Like so:
if(entry.Value is Foo)
{
Foo lFoo = (Foo)entry.Value;
}
else if(entry.Value is Bar)
{
Bar lBar = (Bar)entry.Value;
}
You can make use of Refection to get the value of proerty of the object.
something like this
PropertyInfo info2 = object.GetType().GetProperty("prpertyname");
Object val = info2.GetValue(object, null);
You need to cast entry.Value to the type you need. The Object type itself isn't going to expose the properties you want.
If you just need to access the values, and you know the expected type you can use
foreach(ExpectedType value in v_map.map_set.Values.OfType<ExpectedType>())
{
var property = value.Property;
}
where Property is a property on ExpectedType.
The problem is that you're using an object which isn't typed. So you're going to need to use reflection like this:
PropertyInfo pi = ob.GetType().GetProperty("PropertyName");
var val = pi.GetValue(ob, null);
Now, if the property isn't public then you'll need to employ something else like this:
PropertyInfo pi = ob.GetType().GetProperty("PropertyName", BindingFlags.Instance | BindingFlags.NonPublic);
var val = pi.GetValue(ob, null);
Now, if this is actually a field you're trying to get to, you're going to need to do something different even yet:
FieldInfo fi = ob.GetType().GetField("fieldName");
var val = fi.GetValue(ob);
GetProperty method
BindingFlags enumeration
GetField method

Get Property by String Force Uppercase?

I am using the C# GetPropertymethod using reflection.
obj.GetType().GetProperty("columnName")
However I cannot guarantee the exact casing of the column name as it is being based in from an external source. It maybe ColumnName or columnname
I was thinking if I could just force the string column name to uppercase, but how would I then deal with the Property on the object itself? The getProperty method looks like it needs to be the EXACT casing?
You can use
var prop = GetProperty("columnname",
BindingFlags.Instance |
BindingFlags.Public |
BindingFlags.IgnoreCase);
Note that you'll still need the Instance and Public bit (assuming that this is a public instance property) as otherwise it won't find anything.
You can ignore the case when looking up the property.
GetProperty(fieldname, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
You can always combine reflection with some Linq magic, like this:
var property = typeof (MyType).GetProperties()
.Where(p => p.Name.Equals("MyProperty", StringComparison.InvariantCultureIgnoreCase));
Try:
var yourprop = from x in obj.GetType().GetProperties()
where x.Name.ToUpper() == "a column name".ToUpper()
select x;

Reflection class to get all properties of any object

I need to make a function that get all the properies of an object (including an children objects) This is for my error logging feature.
Right now my code always returns 0 properties.
Please let me know what I'm doing wrong, thanks!
public static string GetAllProperiesOfObject(object thisObject)
{
string result = string.Empty;
try
{
// get all public static properties of MyClass type
PropertyInfo[] propertyInfos;
propertyInfos = thisObject.GetType().GetProperties(BindingFlags.Public | BindingFlags.Static);//By default, it will return only public properties.
// sort properties by name
Array.Sort(propertyInfos,
(propertyInfo1, propertyInfo2) => propertyInfo1.Name.CompareTo(propertyInfo2.Name));
// write property names
StringBuilder sb = new StringBuilder();
sb.Append("<hr />");
foreach (PropertyInfo propertyInfo in propertyInfos)
{
sb.AppendFormat("Name: {0} | Value: {1} <br>", propertyInfo.Name, "Get Value");
}
sb.Append("<hr />");
result = sb.ToString();
}
catch (Exception exception)
{
// to do log it
}
return result;
}
here's what the object looks like:
If you want all of the properties, try:
propertyInfos = thisObject.GetType().GetProperties(
BindingFlags.Public | BindingFlags.NonPublic // Get public and non-public
| BindingFlags.Static | BindingFlags.Instance // Get instance + static
| BindingFlags.FlattenHierarchy); // Search up the hierarchy
For details, see BindingFlags.
The problem with your code is the PayPal Response types are members, NOT properties. Try:
MemberInfo[] memberInfos =
thisObject.GetMembers(BindingFlags.Public|BindingFlags.Static|BindingFlags.Instance);
Your propertyInfos array is returning 0 length for one of my classes. Changing the line to be
propertyInfos = thisObject.GetType().GetProperties();
Results in it being populated. Therefore, this line of code is your problem. It appears if you add the flag
BindingFlags.Instance
to your parameters it will return the same properties as the parameterless call. Does adding this parameter to your list fix the problem?
EDIT: Just saw your edit. Based on the code you posted, it didn't work for me either. Adding the BindingFlags.Instance made it return properties for me. I'd suggest posting the exact code you are having trouble with as your screenshot shows different code.

Is there something like Python's getattr() in C#?

Is there something like Python's getattr() in C#? I would like to create a window by reading a list which contains the names of controls to put on the window.
There is also Type.InvokeMember.
public static class ReflectionExt
{
public static object GetAttr(this object obj, string name)
{
Type type = obj.GetType();
BindingFlags flags = BindingFlags.Instance |
BindingFlags.Public |
BindingFlags.GetProperty;
return type.InvokeMember(name, flags, Type.DefaultBinder, obj, null);
}
}
Which could be used like:
object value = ReflectionExt.GetAttr(obj, "PropertyName");
or (as an extension method):
object value = obj.GetAttr("PropertyName");
Use reflection for this.
Type.GetProperty() and Type.GetProperties() each return PropertyInfo instances, which can be used to read a property value on an object.
var result = typeof(DateTime).GetProperty("Year").GetValue(dt, null)
Type.GetMethod() and Type.GetMethods() each return MethodInfo instances, which can be used to execute a method on an object.
var result = typeof(DateTime).GetMethod("ToLongDateString").Invoke(dt, null);
If you don't necessarily know the type (which would be a little wierd if you new the property name), than you could do something like this as well.
var result = dt.GetType().GetProperty("Year").Invoke(dt, null);
Yes, you can do this...
typeof(YourObjectType).GetProperty("PropertyName").GetValue(instanceObjectToGetPropFrom, null);
There's the System.Reflection.PropertyInfo class that can be created using object.GetType().GetProperties(). That can be used to probe an object's properties using strings. (Similar methods exist for object methods, fields, etc.)
I don't think that will help you accomplish your goals though. You should probably just create and manipulate the objects directly. Controls have a Name property that you can set, for example.

Categories