Search code examples
c#constructorhttprequest

How can I obtain data from a server (HTTP POST) during class construction without putting the HTTP POST in the constructor itself?


I have a class that in order to have all its properties fully populated it needs to obtain some data from the server.

Currently I have a call to the server in its constructor like so:

public class GeometryObject
{
    public GeometryObject(string partName, CADFileType partType)
    {
        InitializeTransformParameters(); 
        CreateDefaultInternalParameters(); 
        CADFile = Server.GetCADFileAsync(partName, partType).Result; // not great having a time consuming action in the constructor but not sure how else to do this.                             
    } 
}

Server.GetCADFileAsync() is essentially a wrapper for HttpClient.PostAsync().

Although this works (provided the call succeeds!!), it smells a bit like a bad design. How is this kind of thing usually approached? I'm using C# 6.


Solution

  • I've seen it done, but it's not exactly good. A more common approach uses a Factory Method, like this:

    public class MyClass
    {
        // private constructor
        private MyClass() {}
    
        // public static method to wrap the constructor. 
        // "Create" is also a common name here,
        // but I prefer "Load" when I *know* it's gonna take a while
        public static MyClass Load()
        {
            // We can call the constructor here, because it's a member of the class
            var result = new MyClass();
            
            // populate required fields here
    
            
            return result;       
        }
    }
    

    Then, instead of new MyClass() you'd use the type like this:

    var myVariable = MyClass.Load();
    

    And so we would adapt the code in the question like this:

    public class GeometryObject
    {
        private GeometryObject() 
        {
            // normal/fast initialization can still go here (but doesn't have to)
            InitializeTransformParameters(); 
            CreateDefaultInternalParameters(); 
        }
    
        public static GeometryObject Load(string partName, CADFileType partType)
        {
            var result = new GeometryObject();
            result.CADFile = Server.GetCADFileAsync(partName, partType).Result;
            return result;                            
        }         
    }