Search code examples
c#genericsmockingproxy-classesexpandoobject

Creating Proxy/Mock Object From/Of Generic Type


I would like to implement the following method:

public static T CreateProxyObject<T>(Dictionary<String,Object> setup) 

With the following Rules:

1) I want to stay as generic as possible means T is not known during compile time and I want to be able to return it to user as the mocked/proxy requested type (user can still use normal intellisense to get object's metadata).

2) It should have all its properties set/setup based on the setup Dictionary:

String-> property name of the object

Object-> the return value for this property

Any other method should be implemented with throwing not implemented exception

I was trying to use mock of T (from Moq framework) but T must be reference type.

Had no success as well with Castle DynamicProxy and RealProxy.

Any Idea?


Solution

  • After searching a bit more I found this answer that guided me to use impromptu-interface which uses expandoobject/dynamic object in order to implement an interface, And together with this answer (which solve the problem of setting the properties dynamically),

    I was able to create the following implementation:

    public static T CreateProxyObject<T>(Dictionary<String,Object> setup) where T : class
    {
       return setup.Aggregate(
              (IDictionary<string, object>) new ExpandoObject(),
                (e, kvSetup) =>
                    {
                        e.Add(kvSetup.Key, kvSetup.Value);
                        return e;
                    }).ActLike<T>();
    
     }
    

    That can be used like this:

    public interface IPerson
    {
        string Name { get; set; }
        int Age { get; set; }
        void Method();
    }
    
    
    
    public class Program
    {
        static void Main(string[] args)
        {
           //Dynamic Expando object
            var p = CreateProxyObject<IPerson>(new Dictionary<string, object>
                                           {
                                               {"Name", "a name"},
                                               {"Age", 13}
                                           });
            var n = p.Name;
            var a = p.Age;
            //Throws: 'System.Dynamic.ExpandoObject' does not contain a definition for 'Method'
            p.Method();
        }
    }