I have a class with custom enum:
public enum Capabilities{
PowerSave= 1,
PnP =2,
Shared=3, }
My class
public class Device
{
....
public Capabilities[] DeviceCapabilities
{
get { // logic goes here}
}
Is there a way using reflection to get the value of this field during runtime?
I tried the following but got null reference exception
PropertyInfo[] prs = srcObj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo property in prs)
{
if (property.PropertyType.IsArray)
{
Array a = (Array)property.GetValue(srcObj, null);
}
}
EDIT: Thanks for your answers, what I really need is a way to get the values dynamically without the need to specify the enum type.
Something like:
string enumType = "enumtype"
var property = typeof(Device).GetProperty(enumType);
Is that possible?
The following should do what you desire.
var property = typeof(Device).GetProperty("DeviceCapabilities");
var deviceCapabilities = (Capabilities[])property.GetValue(device);
Note that the method Object PropertyInfo.GetValue(Object) is new in .NET 4.5. In previous versions you have to add an additional argument for the indices.
var deviceCapabilities = (Capabilities[])property.GetValue(device, null);
This should work:
var source = new Device();
var property = source.GetType().GetProperty("DeviceCapabilities");
var caps = (Array)property.GetValue(source, null);
foreach (var cap in caps)
Console.WriteLine(cap);
If you want to enumerate all the possible values of an Enum and return as an array then try this helper function:
public class EnumHelper {
public static IEnumerable<T> GetValues<T>()
{
return Enum.GetValues(typeof(T)).Cast<T>();
}
}
Then you can simply call:
Capabilities[] array = EnumHelper.GetValues<Capabilities>();
If that isn't what you are after then I'm not sure what you mean.
You can try this
foreach (PropertyInfo property in prs)
{
string[] enumValues = Enum.GetNames(property.PropertyType);
}
Hope it helps.
Related
I have the below scenario
public class TestData
{
public TestEnum EnumTestData{get;set;}
}
public Enum TestEnum
{
Test1,Test2,Test3
}
I have another class which traverse through my TestData class for all properties. Depending on the property type it will generate random data for it. Now when my propertyType is Enum type, How can I know which type of enum it is and how to get either Test1, Test2 or Test3 as my output?
You can get a list of all properties using the Type.GetProperties method:
var targetType = typeof(TestData);
var properties = targetType.GetProperties();
Then check whether it's an Enum type by checking the PropertyInfo.PropertyType and Type.IsEnum properties:
foreach(var prop in properties)
{
if (prop.PropertyType.IsEnum)
{
...
}
}
Finally get a random value using the Enum.GetValues method:
var random = new Random();
...
var values = Enum.GetValues(prop.PropertyType);
var randomValue = ((IList)values)[random.Next(values.Length)];
You can just .ToString() the EnumTestData property, like this:
var test = new TestData();
test.EnumTestData = TestEnum.Test1;
var dummy = test.EnumTestData.ToString();
Note: dummy will be "Test1".
Not entirely sure what you're asking, but this is how you would compare and get the string value of an enum:
var td = new TestData();
// compare
if (td.EnumTestData == TestEnum.Test1)
{
// Will output "Test1"
Console.WriteLine(td.EnumTestData.ToString());
}
Also, I'm sure it's just a typo but it's enum not Enum:
public enum TestEnum
{
Test1,Test2,Test3
}
I have a class called Prescriptions. It has properties that are other classes. So, for example, a property name of Fills would be from the PDInt class which has other properties about the value that I need.
If I want to set the value of the Fills property in the Prescription class it would be something like
Prescription p = new Prescription();
p.Fills.Value = 33;
So now I want to take the name of the Fills property and stuff it in a the tag property in a winform control.
this.txtFills.Tag = p.Fills.GetType().Name;
However when I do this, I get the base class of the property, not the property name. So instead of getting "Fills", I get "PDInt".
How do I get the instantiated name of the property?
Thank you.
Below is an extension method that I use it when I wanna work like you:
public static class ModelHelper
{
public static string Item<T>(this T obj, Expression<Func<T, object>> expression)
{
if (expression.Body is MemberExpression)
{
return ((MemberExpression)(expression.Body)).Member.Name;
}
if (expression.Body is UnaryExpression)
{
return ((MemberExpression)((UnaryExpression)(expression.Body)).Operand)
.Member.Name;
}
throw new InvalidOperationException();
}
}
use it as :
var name = p.Item(x=>x.Fills);
For detail about how method works see Expression Tree in .Net
Check this blogpost which is helpful : http://handcraftsman.wordpress.com/2008/11/11/how-to-get-c-property-names-without-magic-strings/
Do this you need to make USe of reflection feature of .net framework.
Something like this
Type type = test.GetType();
PropertyInfo[] propInfos = type.GetProperties();
for (int i = 0; i < propInfos.Length; i++)
{
PropertyInfo pi = (PropertyInfo)propInfos.GetValue(i);
string propName = pi.Name;
}
You can get you like as this ? ↓
public class Prescription
{
public PDInt Fills;
}
public class PDInt
{
public int Value;
}
Prescription p = new Prescription();
foreach(var x in p.GetType().GetFields())
{
// var type = x.GetType(); // PDInt or X //Fills
}
Maybe this question make you confuse ,but please help me
In .NET 4.0 , language C#
I have two project ,one is the library define classes and attribute mark infors for class, one is the project that process reflection of class declared from that library.
The problem is , without make reference to library , I just use reflection-related classes to read assembly and I have to get value of properties that declared in object class.
For example
---In LIB project , named lib.dll
public class MarkAttribute: Attribute
{
public string A{get;set;}
public string B{get;set;}
}
[Mark(A="Hello" B="World")]
public class Data
{
}
---In Reflection project
public void DoIt()
{
string TypeName="Lib.Data";
var asm=Assembly.LoadFrom("lib.dll");
foreach (var x in asm.GetTypes())
{
if (x.GetType().Name=="Data")
{
var obj=x.GetType().GetCustomAttributes(false);
//now if i make reference to lib.dll in the usual way , it is ok
var mark=(Lib.MarkAttribute)obj;
var a=obj.A ;
var b=obj.B ;
//but if i do not make that ref
//how can i get A,B value
}
}
}
any idea appreciated
If you know the names of the properties you could use dynamic instead of reflection:
dynamic mark = obj;
var a = obj.A;
var b = obj.B;
You can retrieve the attribute's properties using reflection as well:
Assembly assembly = Assembly.LoadFrom("lib.dll");
Type attributeType = assembly.GetType("Lib.MarkAttribute");
Type dataType = assembly.GetType("Lib.Data");
Attribute attribute = Attribute.GetCustomAttribute(dataType, attributeType);
if( attribute != null )
{
string a = (string)attributeType.GetProperty("A").GetValue(attribute, null);
string b = (string)attributeType.GetProperty("B").GetValue(attribute, null);
// Do something with A and B
}
You can invoke the getter of the property:
var attributeType = obj.GetType();
var propertyA = attributeType.GetProperty("A");
object valueA = propertyA.GetGetMethod().Invoke(obj, null)
You need to remove many of the GetTypes() calls, since you already have a Type object. Then you can use GetProperty to retrieve the property of the custom attribute.
foreach (var x in asm.GetTypes())
{
if (x.Name=="Data")
{
var attr = x.GetCustomAttributes(false)[0]; // if you know that the type has only 1 attribute
var a = attr.GetType().GetProperty("A").GetValue(attr, null);
var b = attr.GetType().GetProperty("B").GetValue(attr, null);
}
}
var assembly = Assembly.Load("lib.dll");
dynamic obj = assembly.GetType("Lib.Data").GetCustomAttributes(false)[0];
var a = obj.A;
var b = obj.B;
Is there any way to set the properties of the objects from string. For example I have "FullRowSelect=true" and "HoverSelection=true" statements as string for ListView property.
How to assign these property along with their values without using if-else or switch-case statments? Is there any SetProperty(propertyName,Value) method or similar for this?
Try this:
private void setProperty(object containingObject, string propertyName, object newValue)
{
containingObject.GetType().InvokeMember(propertyName, BindingFlags.SetProperty, null, containingObject, new object[] { newValue });
}
You can use reflection to do this:
myObj.GetType().GetProperty("FullRowSelect").SetValue(myObj, true, null);
You can do this with reflection, have a look at the PropertyInfo class's SetValue method
YourClass theObject = this;
PropertyInfo piInstance = typeof(YourClass).GetProperty("PropertyName");
piInstance.SetValue(theObject, "Value", null);
Try this:
PropertyInfo pinfo = this.myListView.GetType().GetProperty("FullRowSelect");
if (pinfo != null)
pinfo.SetValue(this.myListView, true, null);
First variant is to use reflection:
public class PropertyWrapper<T>
{
private Dictionary<string, MethodBase> _getters = new Dictionary<string, MethodBase>();
public PropertyWrapper()
{
foreach (var item in typeof(T).GetProperties())
{
if (!item.CanRead)
continue;
_getters.Add(item.Name, item.GetGetMethod());
}
}
public string GetValue(T instance, string name)
{
MethodBase getter;
if (_getters.TryGetValue(name, out getter))
return getter.Invoke(instance, null).ToString();
return string.Empty;
}
}
to get a property value:
var wrapper = new PropertyWrapper<MyObject>(); //keep it as a member variable in your form
var myObject = new MyObject{LastName = "Arne");
var value = wrapper.GetValue(myObject, "LastName");
You can also use Expression class to access properties.
There isn't such a method, but you could write one using reflection.
You can look at Reflection. Its possible to find property and set its value thanks to this. But you need to parse your string yourself. And it may be problem geting valid value of correct type from string.
This can be accomplished with reflection, for example look at this question.
I wrote a function that copies the properties of one class to another so make a copy of an object.
So something like
MyObject myObject = myOtherObject.MyCustomCopy(myObject)
where myObject and myOtherObject are of the same type. I do it by bascually doing
myObject.prop1 = myOtherObject.prop1
myObject.prop2 = myOtherObject.prop2
myObject.prop3 = myOtherObject.prop3
return myObject
I am pretty sure in the past I used a .NET object that automaticaly did this, by reflection I guess, but can't remember it ... or an I imagining that such a method exists?
Yes I'm aware of auto mapper but i was sure (not so much now) that there is a .NET object that does the job. Maybe not!
You may take a look at AutoMapper.
public static class ext
{
public static void CopyAllTo<T>(this T source, T target)
{
var type = typeof(T);
foreach (var sourceProperty in type.GetProperties())
{
var targetProperty = type.GetProperty(sourceProperty.Name);
targetProperty.SetValue(target, sourceProperty.GetValue(source, null), null);
}
foreach (var sourceField in type.GetFields())
{
var targetField = type.GetField(sourceField.Name);
targetField.SetValue(target, sourceField.GetValue(source));
}
}
}
You should use AutoMapper it was built for this job.
System.Object.MemberwiseClone()
Try description in this link:
.NET Reflection - Copy Class Properties
This code should work for basic property types, not sure how it'll go for anything complex (lists, arrays, custom classes). Should be a starting point though:
public class MyClass
{
public int A { get; set; }
public string B { get; set; }
}
private void button1_Click(object sender, EventArgs e)
{
MyClass orig = new MyClass() { A = 1, B = "hello" };
MyClass copy = new MyClass();
PropertyInfo[] infos = typeof(MyClass).GetProperties();
foreach (PropertyInfo info in infos)
{
info.SetValue(copy, info.GetValue(orig, null), null);
}
Console.WriteLine(copy.A + ", " + copy.B);
}
I know the OP did not ask for a Type to another Type but my variant is one I use for DI in startup.cs for mismatches in configurations between cloud and local dev environment. My local class generally uses a Interface class behind the scenes to map the configurations. Then I use this method to copy properties where they match in name only. I am not checking property types since these are configurations. AutoMapper was suggested. I don't use AutoMapper because we are restricted by U.S. DOD to certain providers. Getting an ATO is hard enough just using .NET, we don't need any more grief.
using System.Linq;
public static class PropertyCopy
{
public static void CopyAllTo<T,T1>(this T source, T1 target)
{
var type = typeof(T);
var type1 = typeof(T1);
foreach (var sourceProperty in type.GetProperties())
{
foreach (var targetProperty in type1.GetProperties()
.Where(targetProperty => sourceProperty.Name == targetProperty.Name)
.Where(targetProperty => targetProperty.SetMethod != null))
{
targetProperty.SetValue(target, sourceProperty.GetValue(source, null), null);
}
}
foreach (var sourceField in type.GetFields())
{
foreach (var targetField in type1.GetFields()
.Where(targetField => sourceField.Name == targetField.Name))
{
targetField.SetValue(target, sourceField.GetValue(source));
}
}
}
}
In very simple terms: As we know Classes are reference types in C#.NET i.e. when we create a object of a class such as
Customer C1=new Customer();
C1.Id=1;
C1.Name="Rakesh";
Then C1(Reference variable) is stored on memory stack and object new Customer() is stored on Heap.
Hence when we copy a class into another class which is basically your question you can do something like below:
Customer C2=C1;
Doing above will copy the C1 Reference variable into C2 But why I wrote about Stack and Heap because using C2 reference variable you can change the object properties being both C1 and C2 pointing to same object in HEAP.Something Like
C2.Id=1;
C2.Name="Mukesh";
Now if you will try to access C1.Name you will see it is changed to "Mukesh".
you can use JsonConvert like this:
string jsonString = JsonConvert.SerializeObject(MyObject);
MyClass object = JsonConvert.DeserializeObject<MyClass>(jsonString);