how can access sub class properties?, I can access Y properties, in this case Name, but not x, another case is the same but instead of single reference of x, with a list of x, in this second case how iterate every object.
public class X
{
public int ID{get;set;}
public int Name{get;set;}
}
public class y
{
public string Name{get;set;}
public x Reference{get:set;}
}
//second case
public class y
{
public string Name{get;set;}
public List<x> Reference{get:set;}
}
public static void Main()
{
y classY = new y();
y.Name = "some text here";
y.x.ID = "1";
y.x.Name ="some text for x here";
}
// in another class, pass y
// so, in this method I only can get 'y' values, but not x
Hashtable table = new Hashtable();
public void GetProperties(object p)
{
Type mytype = p.GetType();
var properties = mytype.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var property in properties)
{
table.Add(property.Name, property.GetValue(p, null));
}
}
UPDATE
Also try with interface
public interface ISub
{}
public class X : ISub // etc....
if (typeof(ISub).IsAssignableFrom(property.GetType()) ) // this alwas as false
You will have to evaluate each property to know if it is a list or not:
foreach (var prop in properties)
{
var obj = prop.GetValue(p, null);
if (obj is List<x>)
{
var list = obj as List<x>;
// do something with your list
}
else
{
table.Add(prop.Name, obj);
}
}
Related
I want to make a own parser that can parse object values into the <T> Type that contains class with propertys.
the class ASObject is just a Dictionary<string, object>
public class Example {
public string User { get; set; }
public int Id { get; set; }
}
public static class ServiceResultParser<T>
{
public static T Parse(ASObject AS)
{
foreach(var l in AS.Values)
{
}
}
}
Usage:
var Result = ServiceResultParser.Parse<Example>(theobject);
string User = Result.User;
that is only a test class that I called Example
in json we can use JsonConvert.DeserializeObject<T>(value)
and no I dont want parse json.
how can I now parse the value into the Example class?
regarding.
You could check wheter T has a property with a name that matches the Dictionary's key:
public static class ServiceResultParser<T> where T : new()
{
public static T Parse(ASObject AS)
{
var temp = GetObject();
foreach(var l in AS)
{
PropertyInfo[] properties = typeof(T).GetProperties();
foreach (PropertyInfo property in properties)
{
if(property.Name == l.Key) property.SetValue(temp, l.Value);
}
}
return temp;
}
protected T GetObject()
{
return new T();
}
}
You should also check if the properties type match, etc...
I have a following class:
internal class Sensors
{
public JsonSensor<double> IOPcwFlSpr { get; set; } = new JsonSensor<double>();
}
internal class JsonSensor<TType> : IJsonSensor
{
public TType Value { get; set; }
}
I want to build an expression that retrieves that property.
private static readonly List < PropertyInfo > Properties;
static SensorFactory() {
Properties = typeof(Json.Sensors).GetProperties().ToList();
}
public void Test(Json.Sensors jsonUpdate) {
foreach(var property in Properties) {
var getterMethodInfo = property.GetGetMethod();
var parameterExpression = Expression.Parameter(jsonUpdate.GetType(), "x");
var callExpression = Expression.Call(parameterExpression, getterMethodInfo);
var lambda = Expression.Lambda < Func < JsonSensor < double >>> (callExpression);
var r = lambda.Compile().Invoke();
}
}
This throws:
System.InvalidOperationException : variable 'x' of type 'Sensors'
referenced from scope '', but it is not defined
Which makes sense, because I never assigned 'x' with an actual object. How do I add the 'parameter object'?
The key when using expression trees like this is to compile it once using a parameter (ParameterExpression), creating a Func<Foo,Bar> that takes your input (Foo) and returns whatever you wanted (Bar). Then reuse that compiled delegate many times, with different objects.
I can't see exactly what you're trying to do, but I'm guessing it would be something like:
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
namespace Json
{
static class P
{
static void Main()
{
var obj = new Sensors { IOPcwFlSpr = { Value = 42.5 }, Whatever = { Value = 9 } };
foreach(var pair in SomeUtil.GetSensors(obj))
{
Console.WriteLine($"{pair.Name}: {pair.Value}");
}
}
}
public class Sensors
{
public JsonSensor<double> IOPcwFlSpr { get; set; } = new JsonSensor<double>();
public JsonSensor<int> Whatever { get; set; } = new JsonSensor<int>();
}
public interface IJsonSensor
{
public string Value { get; }
}
public class JsonSensor<TType> : IJsonSensor
{
public TType Value { get; set; }
string IJsonSensor.Value => Convert.ToString(Value);
}
public static class SomeUtil
{
private static readonly (string name, Func<Sensors, IJsonSensor> accessor)[] s_accessors
= Array.ConvertAll(
typeof(Sensors).GetProperties(BindingFlags.Instance | BindingFlags.Public),
prop => (prop.Name, Compile(prop)));
public static IEnumerable<(string Name, string Value)> GetSensors(Sensors obj)
{
foreach (var acc in s_accessors)
yield return (acc.name, acc.accessor(obj).Value);
}
private static Func<Sensors, IJsonSensor> Compile(PropertyInfo property)
{
var parameterExpression = Expression.Parameter(typeof(Json.Sensors), "x");
Expression body = Expression.Property(parameterExpression, property);
body = Expression.Convert(body, typeof(IJsonSensor));
var lambda = Expression.Lambda<Func<Json.Sensors, IJsonSensor>>(body, parameterExpression);
return lambda.Compile();
}
}
}
Basic question here, but I'm new to c#. I have code that basically says: if condition A, then execute a code block on property X. If condition B, then execute the same code block on property Y, and so on. Instead of having to duplicate my code blocks just to change one single property name - a.Value.ValueX to a.Value.ValueY - is there a way to call ValueX or ValueY as variables, such as a.Value.{$propertyName} ?
public static class Conditions
{
public static bool A { get; set; }
public static bool B { get; set; }
}
public class MyObjects
{
public int ValueX { get; set; }
public int ValueY { get; set; }
}
public class MyCollection
{
public Dictionary<int, MyObjects> listOfObjects = new Dictionary<int, MyObjects>();
public static void DoConditions()
{
foreach( var a in listOfObjects)
{
if(Conditions.A)
{
// do code using value x
if (a.Value.ValueX > 0)
continue;
}
else if(Conditions.B)
{
// do the exact same code using value Y
if (a.Value.ValueY > 0)
continue;
}
}
}
}
You can do this:
int val = 0;
if(Conditions.A)
val = a.Value.ValueX;
else if(Conditions.B)
val = a.Value.ValueY;
// Your code block here using "val".
Create a variable and populate it with the appropriate property value:
foreach( var a in listOfObjects)
{
int value;
if(Conditions.A)
value = a.Value.ValueX;
else
value = a.Value.ValueY;
if(value > 0)
continue;
//other code using `value`
}
I am getting object of a class AAA from somewhere and I want to add more information in that object. So, I am creating a new class BBB which is derived from AAA. The class BBB has additional field dictionary. I am populating this dictionary in derived class constructor which is taking the Class AAA object and array of item which I want to use as keys of dictionary and values of this dictionary are elements of a field of object of class AAA. I tried to create similar scenario in blow example code:
void Main(){
A obj = new A () ;
obj.prop1 = new int [] {5 ,10, 15} ;
obj.prop2 = "Hello" ;
obj.prop3 = "World" ;
// obj.Dump () ;
B obj2 = new B (new int [] {1,2,3}, obj) ;
// obj2.Dump () ;
}
// Define other methods and classes here
public class A {
public int [] prop1 ;
public string prop2 ;
public string prop3 ;
}
public class B : A {
public Dictionary <int, int> prop4 ;
public B (int [] keys, A a) {
prop4 = new Dictionary <int, int> () ;
if (keys.Length == a.prop1.Length ) {
for (int i = 0 ; i < keys.Length ; i++ ) {
prop4.Add (keys[i], a.prop1[i]) ;
}
// is there a way to obsolete below lines of code???
this.prop1 = a.prop1 ;
this.prop2 = a.prop2 ;
this.prop3 = a.prop3 ;
}
else {
throw new Exception ("something wrong") ;
}
}
}
In derived class constructor, I am filling the properties manually and I do not want to do it. Is there another way to do it. I have more than 20 properties in my actual class.
Can't do what you're asking but I'd suggest creating a copy constructor for class A and using it with your class B constructor:
// Define other methods and classes here
public class A
{
public int[] prop1;
public string prop2;
public string prop3;
public A()
{
}
public A(A orig)
{
prop1 = orig.prop1;
prop2 = orig.prop2;
prop3 = orig.prop3;
}
}
public class B : A
{
public Dictionary<int, int> prop4;
public B(int[] keys, A a) : base( a )
{
prop4 = new Dictionary<int, int>();
if (keys.Length == prop1.Length)
{
for (int i = 0; i < keys.Length; i++)
{
prop4.Add(keys[i], prop1[i]);
}
}
else
{
throw new Exception("something wrong");
}
}
}
What you are implementing here is very similar to a copy constructor. Doing it by hand is the only way I'm afraid!
My advice is to use Properties in your class A definition and override the properties for your class B implementation:
// Define other methods and classes here
public class A
{
public virtual int[] prop1 { get; set; }
public virtual string prop2 { get; set; }
public virtual string prop3 { get; set; }
}
public class B : A
{
public Dictionary<int, int> prop4;
public override int[] prop1
{
get
{
return m_WrappedAInstance.prop1;
}
set
{
m_WrappedAInstance.prop1 = value;
}
}
public override string prop2
{
get
{
return m_WrappedAInstance.prop2;
}
set
{
m_WrappedAInstance.prop2 = value;
}
}
public override string prop3
{
get
{
return m_WrappedAInstance.prop3;
}
set
{
m_WrappedAInstance.prop3 = value;
}
}
A m_WrappedAInstance = null;
public B(int[] keys, A a)
{
m_WrappedAInstance = a;
prop4 = new Dictionary<int, int>();
if (keys.Length == a.prop1.Length)
{
for (int i = 0; i < keys.Length; i++)
{
prop4.Add(keys[i], a.prop1[i]);
}
}
else
{
throw new Exception("something wrong");
}
}
}
Functionally, this will act similarly. The only downside is that your wrapped class A instance can no longer be changed independently of your class B instance. Is this a requirement?
Instance of B (which you are constructing) and instance of A (which you are passing to constructor of B) are not related - they hold different data, they sit on different memory addresses. The only way to update properties/fields of B instance from values of passed A is copying.
Hmmmmmmm... Its a bit unclear and confusing what you up to but take a look at this:
Maybe its not related to what you need but at least it might give you an idea.
This is how you can create a dictionary from all the properties of a type.
public static Dictionary<string, object> DictionaryFromType(object atype)
{
if (atype == null) return new Dictionary<string, object>();
Type t = atype.GetType();
PropertyInfo[] props = t.GetProperties();
Dictionary<string, object> dict = new Dictionary<string, object>();
foreach (PropertyInfo prp in props)
{
object value = prp.GetValue(atype, new object[]{});
dict.Add(prp.Name, value);
}
return dict;
}
Might help you out. If not let me know to remove this question.
Define an array. Then cast the items in the array to individual properties
In class A
public object[] properties;
public int[] prop1 {
get { return (int[]) properties[0]; }
set { properties[0] = value; } }
public string prop2 {
get { return (string)properties[1]; }
set { properties[1] = value ; } }
Constructor of B
public B (int[] keys, A obj)
{
properties = A.properties;
}
Say I have an object Person with the properties below:
public class Person
{
public int ID { get; set; }
public int EmployeeNo { get; set; }
public string JobDescription { get; set; }
public string Code { get; set; }
}
How would I dynamically check the equality of specific properties by name?
eg.
var dynamicEqualityComparer = RetrieveDynamicEqualityComparer("ID", "JobDescription");
var intersectedPersons = listOfPerson1.Intersect(listOfPerson2, dynamicEqualityComparer);
The above snippit would use the default linq intersect method using the dynamically generated equality comparison method which only compares the fields "ID" and "JobDescription".
I would assume that something like this would have been easy to find, but so far have not been able to locate anything of the sort.
Put this in your person class then with your instance you can call equals
public override bool Equals(object obj)
{
return obj.ToString() == this.ToString();
}
public override int GetHashCode()
{
return this.ToString().GetHashCode();
}
public override string ToString()
{
string myState;
myState = string.Format("[ID: {0};EmployeeNo : {1}; JobDescription: {2};Code :{3}]",ID,EmployeeNo,JobDescription,Code);
return myState;
}
since the override of tostring accounts for all state data,in override equals you
simply leverage your own implementation of ToString().
public int Compare(Person x, Person y)
{
if (x.ID == y.ID && x.JobDescription == y.JobDescription)
return 0;
return (x.ID > y.ID) ? 1 : -1;//here you put what condition to return here i put ID just
//for clarity,if u want just return -1 for ex:
}
this is the implementation of the IComparer<> interface of type Person
The solution I came to is below:
The equality comparer class looks like:
public class CustomPropertyEqualityComparer<T>: IEqualityComparer<T> where T : class
{
private readonly string[] _selectedComparisonProperties;
public CustomPropertyEqualityComparer(params string[] selectedComparisonProperties)
{
_selectedComparisonProperties = selectedComparisonProperties;
}
public bool Equals(T x, T y)
{
if (x != null && y != null && x.GetType() == y.GetType())
{
var type = x.GetType();
var comparableProperties = new List<string>(_selectedComparisonProperties);
var objectProperties = type.GetProperties();
var relevantProperties = objectProperties.Where(propertyInfo => comparableProperties.Contains(propertyInfo.Name));
foreach (var propertyInfo in relevantProperties)
{
var xPropertyValue = type.GetProperty(propertyInfo.Name).GetValue(x, null);
var yPropertyValue = type.GetProperty(propertyInfo.Name).GetValue(y, null);
if (xPropertyValue != yPropertyValue && (xPropertyValue == null || !xPropertyValue.Equals(yPropertyValue)))
{
return false;
}
}
return true;
}
return x == y;
}
public int GetHashCode(T obj)
{
var type = typeof(T);
var objectProperties = type.GetProperties();
return objectProperties.Sum(property => property.GetHashCode());
}
}
To create this class, you pass in a list of strings representing the objects property names.
To call this class, I used the following bit of code:
var groupKey = new List<string> {"EmployeeNo", "ID"}.ToArray();
var customEqualityComparer = new CustomPropertyEqualityComparer<object>(groupKey);
This creates a custom equality comparer for any class with the properties "EmployeeNo" and "ID".
I used this comparer when checking if two tables contain the same entries where equality doesn't necessarily mean that every single field is equal..
var existInBothTables = table1.Intersect(table2, customEqualityComparer).ToList();