如何触发泛型类方法递归地更改T的类型

本文关键字:类型 递归 何触发 泛型 泛型类 类方法 | 更新日期: 2023-09-27 18:09:39

我创建了一个泛型类,将一些数据解析为类(MyClass1)的另一个实例。由于MyClass1只有内置的c#类型,我的GenericMethod工作得很好。当MyClass1具有另一个MyClass2属性并且我仍然想调用我的GenericMethod来解析我的数据时,问题开始增长。

我不能在它的作用域中触发我的泛型类方法,因为我需要改变T的类型。有办法解决这个问题吗?

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
}

如何触发泛型类方法递归地更改T的类型

你可以看看这篇文章

或者试试这样

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);
        }
    }
}

根据您的需要,您还可以定义一些关于该属性的附加元信息,指示如果找到它,您想对它做什么。

根据其他人的评论和回答,以下是我想到的,包括一个属性装饰,允许您动态构建对象,并具有以下增强:

  • 属性可以被命名为任何你想要的
  • 不需要if语句作为新的属性添加。
  • 无需更改MyGenericMethod方法。
  • 额外的元信息可以添加到自定义属性中,以便将来添加进一步的自定义。
  • 对象可以根据需要进行深度嵌套。
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 {
}

我调整了这个,所以它可以按原样运行。

编辑:

我还更改了代码以调用正在调用的方法,以避免出现"魔法字符串"。