对类型强制执行静态方法
本文关键字:静态方法 强制执行 类型 | 更新日期: 2023-09-27 18:20:25
我希望一个类具有一个名为GetProduct的强制静态方法,这样客户端代码就可以接受一个类型,并在检查传递的类型是否实现了一个称为ICommandThatHasProduct的接口后安全地调用该静态方法。
这似乎是不可能的,所以现在我正在寻求帮助,寻找实现这一目标的方法。我知道我可以使用反射来查看我传递的类型是否包含一个名为"GetProduct"的方法,但我希望有一种更面向对象的方法(即使用继承)。
任何帮助都将不胜感激!下面的代码是pseudo-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#中的实现。
记住LSP。这有助于避免奇怪的继承树。
我希望类具有一个名为GetProduct的强制静态方法,这样客户端代码就可以接受
Type
对象,并在检查传递的类型是否实现接口后安全地调用该静态方法。
你将通过反射进行呼叫,所以你也必须通过反射进行强制执行。Reflection的全部目的是在运行时执行编译器无法验证的工作;如果您想要的是编译时验证,那么您使用的工具完全错误。不要使用专门为击败编译时验证而设计的工具,如果这正是你想要的!
我希望有一种更面向对象的方法(即使用继承)。
您正在以面向对象的方式进行操作。面向对象是指以对象的形式传递功能单元,并向它们发送"消息"(也称为方法调用),描述您希望对它们执行的操作,并以后期绑定的方式分析这些"消息"。(通常后期绑定是以虚拟调用的形式进行的,但按名称进行后期绑定也可以。)
继承是一种在类之间共享代码并表示语义"是一种"关系的机制;为什么你觉得继承与你的问题有关?
我认为您真正的问题是传递Type
s,而不是您自己的类。GetProduct()
-方法实际上属于表示命令类型的类,但当然不能在实际的Type
上添加该方法。因此,您可以创建自己的类来表示命令的类型。
我猜您正在使用Type
s来通过反射构建实际的Command
s。如果是这样的话,你实际上想要一个"工厂"。(如果创建工厂没有意义,只需创建一个"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");
}
}
}
}
考虑到关于这是否是正确的做法的评论,我认为你知道自己在做什么。下面是一个最小的代码示例:
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();
}
}
}
为什么需要称它为static?你可以这样做:
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();
}
}
您可以始终将实例而不是类型传递给客户端。