Applying a static method to a type

I want the class to have a forced static GetProduct method, so that client code can accept the type and safely call this static method after checking that the passed type implements the ICommandThatHasProduct interface.

This seems to be impossible, so now I am looking for help in finding a way that I can achieve this. I know that I could use reflection to see if the type I passed passed a method called "GetProduct", but I hope there is a more object oriented way (ie Using inheritance).

Any help would be appreciated! The code below is pseudo-C #, will definitely not compile.

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
source share
5 answers

I think your real problem is that you are bypassing Type instead of your own class. GetProduct() method actually belongs to the class that represents the type of command, but of course you cannot add the method to the actual Type . So instead, create your own class to represent the type of command.

I think you are using Type to create the actual Command through reflection. If so, you really want a "Factory". (If it makes no sense to do a factory, just create a CommandType object instead).

Try something like this:

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

}

0
source

The method does not have to be static. Instead, use a member method and create a regular inheritance tree.

I assume you are looking for an abstract factory or a simple implementation of a factory method template in C #.

Remember the LSP . This helps to avoid weird inheritance trees.

+3
source

I want the class to have a forced static GetProduct method, so that client code can accept a Type object and safely call this static method after checking that the passed type implements the interface.

You are about to make a call through Reflection, so you have to force the execution through Reflection. The whole point of Reflection is to do work at runtime that the compiler could not verify; if you want to check compilation time, you are using the exact tool. Do not use a tool specifically designed to prevent compile-time checking if this is what you need!

I hope there is a more object oriented way (i.e. using inheritance).

You do this in an object oriented way. Object orientation is a traversal of units of functionality in the form of objects and sending them “messages” (the so-called method calls) that describe what operations you want to perform on them, and those “messages” that are analyzed at the end. (Usually late binding in the form of virtual calls, but late binding by name is also fine.)

Inheritance is a mechanism for sharing code between classes and representing semantic relationships "it's kind of"; why do you think inheritance is relevant to your problem?

+3
source

Taking on board comments about whether this is correct, I assume that you know what you are doing. Here is an example of a minimal code:

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

Why do you need to set it statically? You can do it:

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

or just this:

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

You can always pass an instance to a client instead of a type.

0
source

Source: https://habr.com/ru/post/1391369/


All Articles