Search code examples
c#reflectionintellisensefactory-patterndynamicobject

C# Approach to create dynamic objects with Intellisense support


I have a client/server application using C#.

In my design, the client will request to server some data filtering and gathering that are supported by server through C# classes and methods.

I have a single server connection that receives the requests and provides the data back to the client. To do so, the client requests the object, the method and the parameters.

So, there client does a request like:

GetData (MyClass, MyMethod, MyParams[]);

It all works fine I´m using currently dynamic method invokation at the server:

        Type type = System.Type.GetType(MyClass);
        object instance = System.Activator.CreateInstance(type);
        MethodInfo method = type.GetMethod(MyMethod);
        object[] parameters = new object[] { MyParams[] };
        var data = method.Invoke(instance, parameters); 

        ... data checking, filtering and returning to client...

I have a problem that I have several different objects and methods, each one with different checking and filtering. As dynamic object does not support Intellisense, my checking code after data is a big mess, difficult to support and even to understand.

I wish to have a different approach to that, where I could get data with Intellisense support (known type). That would make my life easier and code clearer. On the other side, I don´t what build dozen of GetData calls with different combinations.

I´m thinkin of building an object factory, but I´m not sure what kind of pattern shall be best suited here. I´m sure there is a good pattern to be used here, but I can´t see the solution to my problem...

Any help is very much appreciated.


Solution

  • It's hard to determine the complexity of your problem, without more details, but I think you are looking for the strategy pattern

    Runnable example

    abstract class Strategy
      {
        public abstract void AlgorithmInterface();
      }
    
    class ConcreteStrategyA : Strategy
      {
        public override void AlgorithmInterface()
        {
          Console.WriteLine(
            "Called ConcreteStrategyA.AlgorithmInterface()");
        }
      }
    
    class ConcreteStrategyB : Strategy
      {
        public override void AlgorithmInterface()
        {
          Console.WriteLine(
            "Called ConcreteStrategyB.AlgorithmInterface()");
        }
      }
    
    class Context
      {
        private Strategy _strategy;
    
        // Constructor
        public Context(Strategy strategy)
        {
          this._strategy = strategy;
        }
    
        public void ContextInterface()
        {
          _strategy.AlgorithmInterface();
        }
      }
    
    class MainApp
      {
        /// <summary>
        /// Entry point into console application.
        /// </summary>
            static void Main()
            {
              Context context;
    
              // Two contexts following different strategies
              context = new Context(new ConcreteStrategyA());
              context.ContextInterface();
    
              context = new Context(new ConcreteStrategyB());
              context.ContextInterface();
    
              // Wait for user
              Console.ReadKey();
            }
          }
    

    Quote from Design Patterns: Elements of Reusable Object-Oriented Software

    Strategy

    Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

    Applicability

    Use the Strategy pattern when:

    1. many related classes differ only in their behavior. Strategies provide a way to configure a class with one of many behaviors.

    2. you need different variants of an algorithm. For example, you might define algorithms reflecting different space/time trade-offs. Strategies can be used when these variants are implemented as a class hierarchy of algorithms

    3. an algorithm uses data that clients shouldn't know about. Use the Strategy pattern to avoid exposing complex, algorithm-specific data structures.