【问题标题】:Enforcing a static method on a Type对类型强制执行静态方法
【发布时间】:2012-02-11 22:31:31
【问题描述】:

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

【问题讨论】:

标签: c# inheritance polymorphism static-methods


【解决方案1】:

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

我猜你正在使用Types 通过反射构造实际的Commands。如果是这样,您实际上想要一个“工厂”。 (如果创建工厂没有意义,只需创建一个 '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");
    }
  }
}

}

【讨论】:

    【解决方案2】:

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

    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();
        }
    }
    

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

    【讨论】:

    • 因为构造函数的实际实现相当繁重,我不想为了使用该方法而必须实例化它。
    • 如果您可以将这些方法用作静态方法,那么您将不会使用构造函数中的任何内容,所以......只需使用带有该代码的另一个类。它会增加内聚性并减少耦合。
    【解决方案3】:

    就这是否是正确的做法,我假设您知道自己在做什么。这是一个最小的代码示例:

    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();
        }
    }
    }
    

    【讨论】:

      【解决方案4】:

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

      您将通过反射进行调用,因此您也必须通过反射进行强制执行。反射的全部意义在于在运行时完成编译器无法验证的工作;如果您想要的是编译时验证,那么您使用的是完全错误的工具。不要使用专门为击败编译时验证而设计的工具,如果这正是你想要的!

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

      您正在以面向对象的方式进行操作。面向对象是以对象的形式传递功能单元,并向它们发送描述您希望对它们执行的操作的“消息”(也称为方法调用),以及稍后分析的那些“消息”绑定时尚。 (通常后期绑定是虚拟调用的形式,但名称后期绑定也可以。)

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

      【讨论】:

        【解决方案5】:

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

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-09-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-04-24
          • 2017-05-02
          • 2019-07-11
          • 2020-05-26
          相关资源
          最近更新 更多