关于c#:静态类型与代码重用的通用反射

 2020-02-15 

Generic Reflection of static types with code reuse

我有一个方法可以迭代类的字段,并以CSV格式返回其值。 我需要一种让类以通用方式访问此方法的方法。

出于某些原因,静态必须从对象派生,否则会出现编译错误。 在这种情况下,从其他基类派生确实提高了我的代码可重用性。 还有另一种方法可以实现我的目标吗?

我相信我唯一的选择是使我的静态类成为实例类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//a data container used for Mocking in inversion of control
public class FieldContainer : ReflectionHelper<FieldContainer>
{
    public static string Field1 ="Some Data";
    public static string Field2 ="Persons Name";
    public static string Field3 ="3030 Plane Ave.";
}

    public class ReflectionHelper< T >
    {
    public static string ToCSV()
    {
        StringBuilder fieldCollector = new StringBuilder();

        Type type = typeof(T);
        FieldInfo[] fields = type.GetFields();
        foreach (FieldInfo f in fields)
        {
            fieldCollector.Append(f.GetValue(null) +",");
        }

        return fieldCollector.ToString();
    }
    }


您可以将其形成为扩展方法,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static class ReflectionHelperExtensions
{
    public static string ToCSV< T >(this T instance)
    {
        var type = instance.GetType();
        var fields = type.GetFields();
        var fieldCollector = new StringBuilder();        
        foreach (FieldInfo f in fields)
        {
            fieldCollector.Append(f.GetValue(null) +",");
        }
        return fieldCollector.ToString();
    }
}

这样,您的字段容器类不需要从任何给定类型派生,因为这适用于object的所有派生类。


您的代码是完全有效的(至少在技术上)。您的类FieldContainer不是static类,因此可以从ReflectionHelper< T >派生。

但是,通常不会在基类中实现方法ToCSV,因为它基本上可以在ANY类上工作。因为您想使用静态成员,所以扩展方法也不是最好的方法。最简单,最干净的方法是拥有一个实现此方法的静态帮助器类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static class ReflectionHelper
{
    public static string ToCSV< T >()
    {
        StringBuilder fieldCollector = new StringBuilder();

        Type type = typeof(T);
        FieldInfo[] fields = type.GetFields();
        foreach (FieldInfo f in fields)
        {
            fieldCollector.Append(f.GetValue(null) +",");
        }

        return fieldCollector.ToString();
    }
}

您可以像这样使用它:

1
var csv = ReflectionHelper.ToCSV<FieldContainer>();

但是,我看不到,为什么您要完全实现类似的东西。这似乎没有太大意义。


如果您将该类作为实例类型,那很好。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public abstract class ReflectionHelper< T >
{
    protected ReflectionHelper()
    { }


    public static string ToCsv(string delimiter =",")
    {
        var fieldCollector = new StringBuilder();

        var type = typeof(T);
        var fields = type.GetFields();
        foreach (var f in fields)
        {
            fieldCollector.Append(f.GetValue(null) + delimiter);
        }

        return fieldCollector.ToString();
    }
}

public class Something : ReflectionHelper<Something>
{
    protected Something() : base()
    {

    }
    public static string Field1 ="Some Data";
    public static string Field2 ="Persons Name";
    public static string Field3 ="3030 Plane Ave.";
}

您是否考虑过使用扩展方法?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static class ReflectionExtensions
{
     public static string ToCSV(this object input)
     {
         StringBuilder fieldCollector = new StringBuilder();

         Type type = input.GetType();
         FieldInfo[] fields = type.GetFields();
         foreach (FieldInfo f in fields)
         {
             fieldCollector.Append(f.GetValue(null) +",");
         }

         return fieldCollector.ToString();
    }
}

然后,您可以在任何对象上简单地调用以下命令:

1
2
FieldContainer c = new FieldContainer();
string result = c.ToCSV();