Search code examples
c#dynamicinterfacedynamicobject

Create a dynamic object that implements my custom interface


I am creating some custom API. What I need is pass some object to the api that have "static" required propreties and dynamic optional properties.

I have created a dynamic custom object like this:

public class MyDynamicEntity : DynamicObject, IMyDynamicEntity
{
    public string Key { get; set; }
    public string Type { get; set; }
}

And my API has this signature:

void DoWork(MyDynamicEntity myEntity);

Everything "seems" work, but the problem is that the intellisense does not help programmers (that are not me) how to use my API.... Infact to use the api they must write something like this:

dynamic myEntity = new MyDynamicEntity();
myEntity.DynamicPropA = ...;
myEntity.DynamicPropB = ...;
...
myEntity.Key = ...;
myEntity.Type = ...;

They must declare an object of type dynamic, so it is not visible to who use the API the exists two required props: Key andType..

Can anyone have a suggestion how to solve my problem? thanx

PS.: Due to some reasons, I cannot simply create some classes that implements my IMyDynamicEntity interface...

Exactly, I must create a mapping between my MyDynamicEntity class and a strictly "Azure-bounded" class: Microsoft.WindowsAzure.Storage.Table.DynamicTableEntity (or Microsoft.WindowsAzure.Storage.Table.TableEntity). But my API must be generic and not specific to a use case. Furthermore my API cannot expose a DynamicTableEntity (or a TableEntity nor a custom class that inherits one of them) otherwise the client that use my API would import Azure DLLs.

I am looking for a solution easy to remember in some moths to me and easy to understand for who must use my API, so I do not need to explain everyone what they have to do with the API.


Solution

  • You can split dynamic and non-dynamic properties like this:

    interface IMyDynamicEntity {
        string Key { get; set; }
        string Type { get; set; }
    }
    
    public class MyEntity : IMyDynamicEntity
    {        
        public string Key { get; set; }
        public string Type { get; set; }
        public dynamic Properties { get; } = new MyDynamicProperties();
    
        private class MyDynamicProperties : DynamicObject {
    
        }
    }
    

    Then usage becomes:

    var myEntity = new MyEntity();
    myEntity.Properties.DynamicPropA = ...;
    myEntity.Properties.DynamicPropB = ...;                
    myEntity.Key = ...;
    myEntity.Type = ...;
    

    Alternatively, require "required" properties in constructor:

    public class MyDynamicEntity : DynamicObject, IMyDynamicEntity
    {
        public MyDynamicEntity(string key, string type) {
            Key = key;
            Type = type;
        }
        public string Key { get; }
        public string Type { get; }
    }
    

    Then usage becomes:

    dynamic myEntity = new MyDynamicEntity(key, type);
    myEntity.DynamicPropA = ...;
    myEntity.DynamicPropB = ...;