I've created a Generic Class to parse some data into another instance of a class (MyClass1
). Since MyClass1
has only built-in C# types, my GenericMethod
works fine. The problem starts to grow when MyClass1
has another MyClass2
property and I still want to invoke my GenericMethod
to parse my data.
I can't trigger my Generic Class method inside its scope since I need to change the type of T
. Is there any way to solve this problem?
public class MyClass1
{
public int MyIntProperty { get; set; }
public string MyStringProperty { get; set; }
public MyClass2 MyClass2Property { get; set; }
}
public class MyClass2
{
public int MyOtherIntProperty { get; set; }
public string MyOtherStringProperty { get; set; }
public bool MyOtherBoolProperty { get; set; }
}
public class MyGenericClass<T> where T : class
{
public static T MyGenericMethod()
{
T o = (T)Activator.CreateInstance(typeof(T));
PropertyInfo[] pi = typeof(T).GetProperties();
for(int i = 0; i < pi.Count(); i++)
{
if(pi[i].Name == "MyClass2Property")
{
//How to proceed ?
MyGenericClass<???>.MyGenericMethod();
}
else
{
pi[i].SetValue(o, Convert.ChangeType(someValue, pi[i].PropertyType), null);
}
}
}
}
public static void Main(string[] args)
{
MyClass1 mc1 = MyGenericClass<MyClass1>.MyGenericMethod();
//Do something with mc1
}
You can look at this post
and maybe try something like this
public static class MyGenericClass<T> where T : class
{
public static T MyGenericMethod()
{
T o = (T)Activator.CreateInstance(typeof(T));
PropertyInfo[] pi = typeof(T).GetProperties();
for(int i = 0; i < pi.Count(); i++)
{
if(pi[i].Name == "MyClass2Property")
{
//How to proceed ?
Type t = typeof (MyGenericClass<>);
Type genericType = t.MakeGenericType(new System.Type[] { pi[i].PropertyType });
var c = Activator.CreateInstance(genericType);
dynamic mgm = Convert.ChangeType(c, genericType);
mgm.MyGenericMethod();
}
else
{
pi[i].SetValue(o, Convert.ChangeType(someValue, pi[i].PropertyType), null);
}
}
}
Depending on your needs, you could also define some additional meta information about the property indicating what you would like to do with it if found.
Building on others' comments and answers, here is what I came up with including an attribute decoration that allows you to dynamically build objects and has the following enhancements:
MyGenericMethod
method to ever change.using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Dynamic;
public class MyClass1 {
public int MyIntProperty { get; set; }
public string MyStringProperty { get; set; }
[MyCustom()]
public MyClass2 MyClass2Property { get; set; }
}
public class MyClass2 {
public int MyOtherIntProperty { get; set; }
public string MyOtherStringProperty { get { return "oooh, fancy"; } set {} }
public bool MyOtherBoolProperty { get; set; }
}
public static class MyGenericClass<T> where T : class {
public static T MyGenericMethod() {
T o = (T)Activator.CreateInstance(typeof(T));
PropertyInfo[] pi = typeof(T).GetProperties();
for (int i = 0; i < pi.Count(); i++) {
if (pi[i].GetCustomAttributes(true).Any() && pi[i].GetCustomAttributes(true).Where((x) => x is MyCustomAttribute).Any()) {
//How to proceed ?
var c = Activator.CreateInstance(pi[i].PropertyType);
Type t = typeof(MyGenericClass<>);
Type genericType = t.MakeGenericType(new System.Type[] { pi[i].PropertyType });
MethodInfo m = genericType.GetMethod(MethodInfo.GetCurrentMethod().Name);
c = m.Invoke(null, null);
pi[i].SetValue(o, c, null);
} else {
//Normal property assignment.
}
}
return o;
}
}
public class Program {
public static void Main(string[] args) {
MyClass1 mc1 = MyGenericClass<MyClass1>.MyGenericMethod();
//Do something with mc1
Console.WriteLine(mc1.MyClass2Property.MyOtherStringProperty);
Console.ReadLine();
}
}
[AttributeUsage(AttributeTargets.Property, AllowMultiple=false)]
public class MyCustomAttribute : Attribute {
}
I tweaked this so it can be run as is.
Edit:
I also changed the code to invoke the method being called on itself to avoid a "magic string".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With