我有一个类,它有三个重载方法。比方说,有:
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)
,但它没有用。是否可能,或者我必须将每个方法“投射”到另一个方法中?
编辑:子类有各种方法和字段,我希望只能为父类访问它们。这就是为什么我不希望父母在它之后得出它。我没有解释,抱歉,如果它看起来像子类只包含这三种方法。这些是我希望作为父类的公共方法可访问的方法。
答案 0 :(得分:2)
为什么不做
class MyChildClass : MyBaseClass
{
}
效果相同,代码更少,这种方式MyChildClass
是MyBaseClass
如果您使用反射实现某种通用外观,那么您只需降低性能,绕过类型安全的好处并推迟发现问题。
你还有一个"有一个"而#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");