I use MVC and c# .. how can i get property's value?
Thank you
foreach (var prop in this.GetType().GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(CalcProgressAttribute))))
{
//i need prop 's value here
}
Try this, to make GetProperty work as you expect:
foreach (var prop in this.GetType().GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).Where(prop => Attribute.IsDefined(prop, typeof(CalcProgressAttribute))))
{
object value = prop.GetValue(this, null);
}
I don't know wether your foreach loop works, because i can not proof the following part of your code:
.Where(prop => Attribute.IsDefined(prop, typeof(CalcProgressAttribute)))). But without the Where the loop will go through all properties.
Related
I am getting the exception mentioned in the title at the line of code
values[i] = Props[i].GetValue(item, null);
and I am not sure what is causing this. Any help would be appreciated.
public static DataTable ToDataTable<T>(List<T> items)
{
DataTable dataTable = new DataTable(typeof(T).Name);
PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo prop in Props)
{
var type = (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>) ? Nullable.GetUnderlyingType(prop.PropertyType) : prop.PropertyType);
dataTable.Columns.Add(prop.Name, type);
}
foreach (T item in items)
{
var values = new object[Props.Length];
for (int i = 0; i < Props.Length; i++)
{
values[i] = Props[i].GetValue(item, null);
}
dataTable.Rows.Add(values);
}
return dataTable;
}
If this line is throwing the exception
values[i] = Props[i].GetValue(item, null);
...then it means you have a property that requires a parameter. In c#, the only type of property that takes a parameter is an indexer. My guess is you should just exclude the indexer from the loop.
See this question which tells you how to detect an indexer.
You can probably fix this by changing one line. Change this...
PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
...to this....
PropertyInfo[] Props = typeof(T)
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.GetIndexParameters == null))
.ToArray();
The issue was actually in the data that I passed into the method(a list of strings). It appeared that the GetValue() method was looking for an object. I created a class with a string property and changed my list type that was being passed in to the class and set the property in the class to the string that I was passing to the list in my foreach loop. Sorry if this doesn't make sense just trying to explain how I solved this, but the problem probably could have been solved a number of ways. Thanks, all.
I have this below piece of code, which i always highlighted by SONAR as a MAJOR issue, because of violation of a rule called with the below message.
Multiple (3) calls to virtual property 'System.String System.Reflection.MemberInfo::get_Name()'.
And the rule description says
AvoidRepetitiveCallsToPropertiesRule
gendarme : AvoidRepetitiveCallsToPropertiesRule
The rule warn if virtual, or unlikely to be inline-able, property getters are called several times by a method. In most cases repetitive calls simply requires more time without any gains since the result will always be identical. You should ignore the reported defects if a different value is expected each time the property is called (e.g. calling DateTime.Now).**
private static void OverrideConfigurationValues(ConfigA configa,
ConfigB configb, ConfigC configc)
{
Type t = configa();
var properties = t.GetProperties(BindingFlags.Public | BindingFlags.Instance);
var overriddenvalues = new Dictionary<string, object>();
foreach (var prop in properties)
{
var value = prop.GetValue(configa,null);
if (value != null)
{
overriddenvalues.Add(prop.Name, value);
}
}
Type b = configb.GetType();
foreach (var prop in b.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
if (!overriddenvalues.ContainsKey(prop.Name))
{
var value = prop.GetValue(b,null);
if (value != null)
{
overriddenvalues.Add(prop.Name, value);
}
}
}
foreach (var overriddenvalue in overriddenvalues)
{
var overriden = overriddenvalue;
foreach (var prop in configa.GetType().GetProperties().Where(prop => prop.Name == overriden.Key))
{
prop.SetValue(configa, overriddenvalue.Value,null);
}
}
}
If the SONAR is complaining about the line prop.Name which i have inside the foreach loop? How can i avoid it?
Ron Beyer's comments are proper answers to this question.
So, your code would look like this based on his comments:
...
foreach (var prop in b.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
var propName = prop.Name;
if (!overriddenvalues.ContainsKey(propName))
{
var value = prop.GetValue(b,null);
if (value != null)
{
overriddenvalues.Add(propName, value);
}
}
}
...
Note that the support of Gendarme rules was dropped in the 3.0 version of the C# plugin.
I'm trying to populate a generic List< T > from another List< U > where the field names match, something like the untested pseudocode below. Where I'm having problems is when T is a string, for instance, which has no parameterless constructor. I've tried adding a string directly to the result object, but this gives me the obvious error -- that a string is not of Type T. Any ideas of how to solve this issue? Thanks for any pointers.
public static List<T> GetObjectList<T, U>(List<U> givenObjects)
{
var result = new List<T>();
//Get the two object types so we can compare them.
Type returnType = typeof(T);
PropertyInfo[] classFieldsOfReturnType = returnType.GetProperties(
BindingFlags.Instance |
BindingFlags.Static |
BindingFlags.NonPublic |
BindingFlags.Public);
Type givenType = typeof(U);
PropertyInfo[] classFieldsOfGivenType = givenType.GetProperties(
BindingFlags.Instance |
BindingFlags.Static |
BindingFlags.NonPublic |
BindingFlags.Public);
//Go through each object to extract values
foreach (var givenObject in givenObjects)
{
foreach (var field in classFieldsOfReturnType)
{
//Find where names match
var givenTypeField = classFieldsOfGivenType.Where(w => w.Name == field.Name).FirstOrDefault();
if (givenTypeField != null)
{
//Set the value of the given object to the return object
var instance = Activator.CreateInstance<T>();
var value = field.GetValue(givenObject);
PropertyInfo pi = returnType.GetProperty(field.Name);
pi.SetValue(instance, value);
result.Add(instance);
}
}
}
return result;
}
If T is string and you have already created custom code to convert your givenObject to a string, you just need to do an intermediate cast to object to add it to a List<T>:
public static List<T> GetObjectList2<T, U>(List<U> givenObjects) where T : class
{
var result = new List<T>();
if (typeof(T) == typeof(string))
{
foreach (var givenObject in givenObjects)
{
var instance = givenObject.ToString(); // Your custom conversion to string.
result.Add((T)(object)instance);
}
}
else
{
// Proceed as before
}
return result;
}
Incidentally, you are adding an instance of T to result for every property of T that matches a property name in U and for every item in givenObjects. I.e. if givenObjects is a list of length 1 and T is a class with 10 matching properties, result could end up with 10 entries. This looks wrong. Also, you need to watch out for indexed properties.
As an alternative to this approach, consider using Automapper, or serializing your List<U> to JSON with Json.NET then deserializing as a List<T>.
I'm working in a project to get some information about Issuers. In MainWindow activity I have this line of code:
builder.AddCustomAttributes(typeof(IssuerActivity), new DesignerAttribute(typeof(IssuerDesigner)));
So I have a IssuerDesigner that I put in a listbox all of the Issuers in his contructor method and I save in an Issuer [] all of these.
Now, when I execute this rehosted workflow, I need to send this Issuer[] to IssuerActivity to analized in a foreach task everyone of them...
The question is: ¿What have I to do to for IssuerActivity gets Issuer[] that It's assigned in IssuerDesigner?
Your question is hard to follow but I beleive this is what you are looking for. You will have to use Reflection on your object to be able to grab the Attribute Values. It should be something like this.
MemberInfo[] members = builder.GetType().GetProperties();
foreach (MemberInfo m in members)
{
if (m.MemberType == MemberTypes.Property)
{
PropertyInfo p = m as PropertyInfo;
object[] attribs = p.GetCustomAttributes(false);
foreach (object attr in attribs)
{
IssuerDesigner d = attr as IssuerDesigner;
if (d != null)
{
foreach(object obj in d.Issuer)
{
DoSomething(obj);
}
}
}
}
}
I have a C# class that I want to loop through the properties as a key/value pair but don't know how.
Here is what I would like to do:
Foreach (classobjectproperty prop in classobjectname)
{
if (prop.name == "somename")
//do something cool with prop.value
}
Yup:
Type type = typeof(Form); // Or use Type.GetType, etc
foreach (PropertyInfo property in type.GetProperties())
{
// Do stuff with property
}
This won't give them as key/value pairs, but you can get all kinds of information from a PropertyInfo.
Note that this will only give public properties. For non-public ones, you'd want to use the overload which takes a BindingFlags. If you really want just name/value pairs for instance properties of a particular instance, you could do something like:
var query = foo.GetType()
.GetProperties(BindingFlags.Public |
BindingFlags.Instance)
// Ignore indexers for simplicity
.Where(prop => !prop.GetIndexParameters().Any())
.Select(prop => new { Name = prop.Name,
Value = prop.GetValue(foo, null) });
foreach (var pair in query)
{
Console.WriteLine("{0} = {1}", pair.Name, pair.Value);
}
Check out the solutions here - although that restricts to public properies the approach should work for you to get them all.