在Type上实施静态方法

时间:2012-01-17 03:13:05

标签: c# inheritance polymorphism static-methods

我希望一个类有一个名为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");
    }
}

5 个答案:

答案 0 :(得分:3)

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

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

牢记LSP。它有助于避免看起来奇怪的继承树。

答案 1 :(得分:3)

  

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

你将通过Reflection进行调用,所以你也必须通过Reflection进行执行。反思的重点是在运行时工作,编译器无法验证;如果您想要的是编译时验证,那么您使用的是错误的工具。如果您想要的话,请不要使用专门用于击败编译时验证的工具!

  

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

你正在以面向对象的方式做这件事。面向对象是以对象的形式传递功能单元,并向它们发送“消息”(也称为方法调用),描述您要对它们执行哪些操作,以及在后期分析的那些“消息”时尚潮流。 (通常后期绑定采用虚拟调用的形式,但后期按名称绑定也很好。)

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

答案 2 :(得分: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 :(得分: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();
    }
}

您始终可以将实例传递给客户端而不是类型。

答案 4 :(得分:0)

我认为你真正的问题是你传递的是Type而不是你自己的一类。 GetProduct() - 方法实际上属于表示命令类型的类,但当然您无法在实际Type上添加该方法。因此,请创建自己的类来表示命令的类型。

我猜您正在使用Type来通过反射构建实际的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");
    }
  }
}

}

相关问题