C# - 将所有方法参数传递给另一个方法?

时间:2012-12-12 11:02:29

标签: c# oop

我有一个类,它有三个重载方法。比方说,有:

class MyChildClass
{
    public void myMethod(int i)
        { /* do something with i */ }
    public void myMethod(int a, string b)
        { /* get i from a and b and call: */ myMethod(i); }
    public void myMethod(string c, string d)
        { /* get i from c and d and call: */ myMethod(i); }
}

现在我希望这个类成为其他(父)类中的私有字段,但我需要这三个方法才能访问。现在,我刚刚做了:

class MyBaseClass
{
    private MyChildClass myObject = new myChildClass(); // or similar
    public void myMethod(int i) 
        { myObject.myMethod(i);    }
    public void myMethod(int a, string b) 
        { myObject.myMethod(a, b); }
    public void myMethod(string c, string s) 
        { myObject.myMethod(c, d); }
}

有没有办法将它作为一种简短方法实现?看起来像:

public void myMethod(unknownListOfArgumentsOfDifferentTypes args)
    { myObject.myMethod(args); }

我尝试使用public void myMethod(params object[] something),但它没有用。是否可能,或者我必须将每个方法“投射”到另一个方法中?

编辑:子类有各种方法和字段,我希望只能为父类访问它们。这就是为什么我不希望父母在它之后得出它。我没有解释,抱歉,如果它看起来像子类只包含这三种方法。这些是我希望作为父类的公共方法可访问的方法。

3 个答案:

答案 0 :(得分:2)

为什么不做

class MyChildClass : MyBaseClass
{
}

效果相同,代码更少,这种方式MyChildClassMyBaseClass


如果您使用反射实现某种通用外观,那么您只需降低性能,绕过类型安全的好处并推迟发现问题。

你还有一个"有一个"而#34;是一个"与你的班级名称不一致的关系。


如果您想放弃这种简单性及其相关优惠,您可以使用此帖子中接受的GetMethodBySig扩展名。

像这样,

class SemiGenericFacade<T> where T : new()
{
    private readonly t = new T();

    public void CallVoidOnT(string name, params object[] parameters)
    {
        var paramTypes = parameters.Select(p => typeof(p))

        var match = typeof(T).GetMethodBySig(typeof(void), paramTypes)
            .Single(mi => mi.Name == name);

        match.Invoke(this.t, parameters);
    }
}

根据Piotr Justyna的评论,实施和使用这种方法会导致猫变成老虎并吃掉她的小猫。


如果您这样做,添加到链接的扩展名

是有意义的
public static class Extensions
{
    public static MethodInfo GetMethodByNameThenSig(
        this Type type,
        string name, 
        Type returnType, 
        params Type[] parameterTypes)
    {
        return type.GetMethods().Where((m) =>
        {
            if (m.Name != name)
            {
                return false;
            }

            if (m.ReturnType != returnType)
            {
                return false;
            }

            var parameters = m.GetParameters();
            if ((parameterTypes == null || parameterTypes.Length == 0))
            {
                return parameters.Length == 0;
            }

            if (parameters.Length != parameterTypes.Length)
            {
                return false;
            }

            for (int i = 0; i < parameterTypes.Length; i++)
            {
                if (parameters[i].ParameterType != parameterTypes[i])
                {
                    return false;
                }
            }

            return true;
        }).Single();
    }
}

你可以这样使用,

class GenericFacade<T> where T : new()
{
    private readonly t = new T();

    public void CallOnInternal(string name, params object[] parameters)
    {
        var paramTypes = parameters.Select(p => typeof(p))

        var match = typeof(T).GetMethodByNameThenSig(
            name,
            typeof(void),
            paramTypes);

        match.Invoke(this.t, parameters);
    }

    public TResult CallOnInternal<TResult>(string name, params object[] parameters)
    {
        var paramTypes = parameters.Select(p => typeof(p))

        var match = typeof(T).GetMethodByNameThenSig(
            name,
            typeof(TResult),
            paramTypes);

        return (TResult)match.Invoke(this.t, parameters);
    }
}

最终编辑

查看涉及使用反射并考虑与类型安全性损失相关的成本的代码。我建议最好建立一个&#34; has-a&#34;以传统方式明确表达关系。

答案 1 :(得分:1)

您可以使用public void myMethod(params object[] something),如下所示:

public static void Main()
{
    UnknownArgumentsMethod1(1, 2, 3, "foo");
}

public static void UnknownArgumentsMethod1(params object[] list)
{
    UnknownArgumentsMethod2(list);
}

public static void UnknownArgumentsMethod2(params object[] list)
{
    foreach (object o in list)
    {
        if (o.GetType() == typeof(int))
        {
            Console.WriteLine("This is an integer: " + (int)o);
        }
        else if (o.GetType() == typeof(string))
        {
            Console.WriteLine("This is a string: " + (string)o);
        }
    }
}

答案 2 :(得分:1)

显而易见的答案是继承。

在你的情况下(即使类的名称另有说明),这样做的方法是继承BaseClass中的ChildClass,这样你就可以通过BaseClass公开ChildClass中的方法。

例如:

class MyBaseClass: MyChildClass
{
}

如果这些类没有关联,你只想在MyBaseClass中有一个MyChildClass实例,但是只暴露一组特定的方法,但是没有将其他方法设为私有,你可以做的就是通过一个只接口的方式公开MyChildClass实例暴露必要的字段如下:

public class BaseClass
{
    public  IChildClass ChildClassInstance = new ChildClass();
}

public class ChildClass : IChildClass
{
    public void myMethod(int i)
    { /* do something with i */ }
    public void myMethod(int a, string b)
    { /* get i from a and b and call: */ myMethod(i); }
    public void myMethod(string c, string d)
    { /* get i from c and d and call: */ myMethod(i); }
}

public interface IChildClass
{
    void myMethod(int i);
    void myMethod(int a, string b);
}

然后您只能访问允许通过基类实例公开的方法:

BaseClass test = new BaseClass();
test.ChildClassInstance.myMethod(1);
test.ChildClassInstance.myMethod(1,"test");