通过反射调用类参数的方法

时间:2015-10-23 03:55:13

标签: c# .net reflection

我刚刚开始使用C#反射,我遇到了调用以内部类作为参数的方法的问题:

示例类:

public class MyClass 
{
    public class CustomColor 
    {
        public int h;
        public int s;
        public int v;
    }

    public string[] ConvertColors(List<CustomColor> colors)
    {
        //...
    }
}

我用来调用此类中其他方法的代码:

FieldInfo info = cInstanceContainerObject.GetType().GetField("_myClass", BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance);
dynamic myClassObject = info.GetValue(cInstanceContainerObject);

允许我这样做:

myClassObject.SomeSampleMethod(int sampleParam);

但是,我一直在想弄清楚如何为上面的ConvertColors方法创建适当的参数。 :(

3 个答案:

答案 0 :(得分:0)

我不确定您是如何创建cInstanceContainerObject的。我正在使用MethodInfo.Invoke。以下是代码:

//Your class
public class MyClass 
{
    public class CustomColor 
    {
        public int h;
        public int s;
        public int v;
    }

    public string[] ConvertColors(List<CustomColor> colors)
    {
        return new string[]{"1"};
    }
}

//Usage
MyClass mc = new MyClass();
    MyClass.CustomColor cc = new MyClass.CustomColor();

    Type t = mc.GetType();
    MethodInfo mi = t.GetMethod("ConvertColors");
    List<MyClass.CustomColor> lst = new List<MyClass.CustomColor>
    {   
        new MyClass.CustomColor(),
        new MyClass.CustomColor()
    };
    var x = (string[])mi.Invoke(mc,new object[]{lst});
    Console.WriteLine (x.Count());

答案 1 :(得分:0)

汤姆,

尝试传递您想要转换的颜色作为参考。

在下面的示例中,您作为参考传入的颜色(CustomColor)将被更新,而不是返回字符串。

所以,不要像以下那样调用方法:

string[] colors = ConvertColors(yourColorList, foo, bar);

它可以改为:

ConvertColors(yourColorList, foo, bar);

示例:

public class MyClass
{
    public class CustomColor
    {
        public int h;
        public int s;
        public int v;
    }

    public enum Convert { H, S, V, HS, HV, SV, HSV };

    public void ConvertColors(ref List<CustomColor> colors, Convert type,
        ref CustomColor changeAmt)
    {
        // Variables to change H, S, and V from changeAmt parameter:
        int changeH = changeAmt.h;
        int changeS = changeAmt.s;
        int changeV = changeAmt.v;

        // Change the actual colors which were passed as 'colors' parameter.
        switch (type)
        {
            // Change H.
            case Convert.H:
                foreach (CustomColor c in colors)
                    c.h += changeH;
                break;

            // Change S.
            case Convert.S:
                foreach (CustomColor c in colors)
                    c.s += changeS;
                break;

            // Change V.
            case Convert.V:
                foreach (CustomColor c in colors)
                    c.v += changeV;
                break;

            // Change HS.
            case Convert.HS:
                foreach (CustomColor c in colors)
                {
                    c.h += changeH;
                    c.s += changeS;
                }
                break;

            // Change HV.
            case Convert.HV:
                foreach (CustomColor c in colors)
                {
                    c.h += changeH;
                    c.v += changeV;
                }
                break;

            // Change SV.
            case Convert.SV:
                foreach (CustomColor c in colors)
                {
                    c.s += changeS;
                    c.v += changeV;
                }
                break;

            // Change HSV.
            case Convert.HSV:
                foreach (CustomColor c in colors)
                {
                    c.h += changeH;
                    c.s += changeS;
                    c.v += changeV;
                }
                break;
        }
    }
}

说明:

'enum'允许您为方法创建自定义参数:

public enum Convert { H, S, V, HS, HV, SV, HSV };

'switch'语句允许您处理这些参数:

switch (type)
        {
            case Convert.H:
                // Do something
                return;
            case Convert.S:
                // Do something
                return;
            case Convert.V:
                // Do something
                return;

创建要作为新CustomColor创建的更改实例,并将对CustomColors列表,自定义参数以及对更改的引用的引用作为CustomColor传递:

private void AnyMethod()
    {
        // Create first custom color.
        CustomColor color1 = new CustomColor();
        color1.h = 50;
        color1.s = 25;
        color1.v = 35;

        // Create second custom color.
        CustomColor color2 = new CustomColor();
        color2.h = 50;
        color2.s = 25;
        color2.v = 35;

        // Create third custom color.
        CustomColor color3 = new CustomColor();
        color3.h = 50;
        color3.s = 25;
        color3.v = 35;

        // Add to list of custom colors.
        List<CustomColor> colorList = new List<CustomColor>();
        colorList.Add(color1);
        colorList.Add(color2);
        colorList.Add(color3);

        // Create changes as a new color.
        CustomColor colorChange = new CustomColor();
        colorChange.h = -10;
        colorChange.s = 47;
        colorChange.v = -15;

        // Update all colors in your list.
        ConvertColors(ref colorList, Convert.HSV, ref colorChange); // BOOM.
    }

如果您希望以后获得字符串:

string[] hsvStrings =
        {
            color1.h.ToString(),
            color1.s.ToString(),
            color1.v.ToString(),
            // Continue...
        };

答案 2 :(得分:0)

在一个不眠之夜后,我实际上想出了如何实现这一目标。这两个答案确实帮助我看到了导致我得到答案的可能性,但是我必须在不引用外部DLL或对其进行任何修改的情况下实现这一点,只需通过Reflection获取它的主要对象的实例,然后调用各种其中的方法(其中一些只需要DLL本身提供的类,如我的例子所示)。

我的解决方案是这样的(随意提供更好的选择):

使用方法参数:

获取List和CustomColor的类型
Type listType = myClassObject.GetType()
                             .GetMethod("ConvertColors")
                             .GetParameters()[0]
                             .ParameterType;

Type colorType = myClassObject.GetType()
                 .GetMethod("ConvertColors")
                 .GetParameters()[0]
                 .ParameterType
                 .GetProperty("Item")
                 .PropertyType;

然后使用Activator创建整个列表和各个CustomColors的单个实例:

dynamic colorList = Activator.CreateInstance(listType);
dynamic customColor = Activator.CreateInstance(colorType);
colorList.Add(customColor);

myClassObject.ConvertColors(colorList); //works!