2012-01-17 86 views
4

我希望类有一个名为GetProduct的强制静态方法,以便客户端代码可以接受类型并在检查传入类型实现名为ICommandThatHasProduct的接口后安全地调用该静态方法。在类型上实现静态方法

看来,这是不可能的,所以现在我正在寻求帮助找到一种方法,我可以实现这一点。我知道我可以使用反射来查看我传递的类型是否包含一个名为“GetProduct”的方法,但我希望有更多的面向对象的方法(即使用继承)。

任何帮助将不胜感激!下面的代码是伪c#,绝对不会编译。

public interface ICommandThatHasProduct 
{ 
    object GetProduct(int id); 
} 

public abstract class Command : ICommandThatHasProduct 
{ 
    // I want to be able to make the GetProduct method static 
    // so that calling code can safely call it 
    public static object GetProduct(int id) 
    { 
     // do stuff with id to get the product 
    } 

    public object Execute() 
    { 
     CommandWillExecute(); 
    } 

    public abstract object CommandWillExecute(); 
} 

public class Program 
{ 
    public Program(Type type, int productId) 
    { 
     if(type == ICommandThatHasProduct) 
     { 
      // Create the args 
      var args = object[1]{ productId }; 

      // Invoke the GetProduct method and pass the args 
      var product = type.InvokeMethod("GetProduct", args); 

      //do stuff with product 
     } 

     throw new Execption("Cannot pass in a Command that does not implement ICommandHasProduct"); 
    } 
} 
+4

'static'方法并不真正适用于一般的面向对象的概念。 – 2012-01-17 03:15:05

+0

有没有静态继承,所以反射可能是唯一的方法 – BrokenGlass 2012-01-17 03:16:10

+1

可能重复的[c#:继承/接口静态成员?](http://stackoverflow.com/questions/1128361/c-inherited-interface-static-member )事实上,几乎所有的[这些问题](http://stackoverflow.com/search?q=%5Bc%23%5D+static+interface)已经解决了这个问题。 – 2012-01-17 03:26:11

回答

0

我认为你真正的问题是你正在传递Type而不是你自己的一类。 GetProduct() - 方法实际上属于表示命令类型的类,但当然不能将该方法添加到实际的Type中。所以相反,让你自己的类来表示命令的类型。

我想你正在使用Type s通过反射来构建实际的Command。如果是这样,你实际上需要一个'工厂'。 (如果制造工厂没有意义,那么只需创建一个'CommandType'对象)。

尝试这样:

public interface IFactory{ 
    object Create(); 
} 

public interface IFactoryThatHasProduct: IFactory 
{ 
    object GetProduct(int id); 
} 

public class MyCommand 
{ 
    //... 
} 

public class MyCommandFactory:IFactoryThatHasProduct 
{ 
    object Create(){ 
    return new MyCommand(); 
    } 

    object GetProduct(int id){ 
    return //TODO 
    } 
} 

public class Program 
{ 
    public Program(IFactory factory, int productId) 
    { 
    // consider just having the method take IFactoryThatHasProduct instead of IFactory 
    if(factory is IFactoryThatHasProduct){ 
     var factoryThatHasProduct = (IFactoryThatHasProduct) factory; 
     var product = factoryThatHasProduct.GetProduct(productId); 
    } 
    else{ 
     throw new Exception("Cannot pass in a factory that does not implement IFactoryThatHasProduct"); 
    } 
    } 
} 

}

3

方法不一定是静态的。改用成员方法,并创建通常的继承树。

我猜你正在寻找abstract factory或C#中的简单工厂方法模式实现。

记住LSP。它有助于避免奇怪的继承树。

0

考虑到这是否是正确的路要走,我会假设你知道你在做什么。下面是一个最小的代码示例:

using System; 
using System.Reflection; 

namespace EnforceStaticMethod 
{ 
class Program 
{ 
    static void Main() 
    { 
     var objA = GetProduct(typeof (TypeA), 1); 
     var objB = GetProduct(typeof (TypeB), 2); 

     Console.WriteLine("objA has type: " + objA.GetType()); 
     Console.WriteLine("objB has type: " + objB.GetType()); 
    } 

    static object GetProduct(Type type, int id) 
    { 
     var argTypes = new[] {typeof (int)}; 
     var method = type.GetMethod("GetProduct", BindingFlags.Static | BindingFlags.Public, null, argTypes, null); 
     if (method == null) 
     { 
      throw new ArgumentException("Type does not have GetProduct method: " + type); 
     } 

     var args = new object[] {id}; 
     return method.Invoke(null, args); 
    } 
} 

class TypeA 
{ 
    public static object GetProduct(int id) 
    { 
     return new TypeA(); 
    } 
} 

class TypeB 
{ 
    public static object GetProduct(int id) 
    { 
     return new TypeB(); 
    } 
} 
} 
3

我想一个类有一个名为GetProduct强迫静态方法,使客户端代码可以接受Type对象,并安全地调用静态方法检查所传递的类型后,实现一个接口。

您将通过Reflection进行呼叫,因此您将不得不通过Reflection来执行强制操作。 Reflection的全部要点是在编译器无法验证的运行时下工作;如果你想要的是编译时验证,那么你正在使用错误的工具。不要使用专门设计的工具失败编译时验证,如果这是你想要的东西!

我希望有一个更面向对象的方式(即使用继承)。

你正在做它的面向对象的方式。面向对象是关于以对象形式传递函数单元,并向它们发送“消息”(又称方法调用),它们描述了你想要对它们执行的操作,以及那些在晚些时候被分析的“消息”时尚。 (通常后期绑定是虚拟调用的形式,但后期的名称绑定也可以。)

继承是一种用于在类之间共享代码并表示语义的机制“是一种”关系;你为什么觉得继承与你的问题有关?

0

为什么你需要静态调用它?你可以这样做:

public class Client 
{ 
    public void DoSomethingWith<T>() where T : ICommandThatHasProduct, new() 
    { 
     var command = new T(); 
     var products = command.GetProducts(); 
    } 
} 

或者只是这样的:

public class Client 
{ 
    public void DoSomethingWith(ICommandThatHasProduct command) 
    { 
     var products = command.GetProducts(); 
    } 
} 

可以实例总是传递到客户端,而不是类型。

+0

由于构造函数的实际实现非常繁重,我不想仅仅为了使用该方法而实例化它。 – Chris 2012-01-17 05:04:13

+0

如果您可以将这些方法用作静态方法,那么您将不会使用构造函数中的任何内容,所以...只需使用另一个具有该代码的类即可。它会增加凝聚力并减少耦合。 – ivowiblo 2012-01-17 13:22:30

相关问题