Home > Back-end >  Generic builder for populating properties pattern
Generic builder for populating properties pattern

Time:07-14

I created a builder class to populate properties in my models for testing scenarios

    public partial class ModelBuilder
    {
        private Model myModel;
        public ModelBuilder CreateNew(int id)
        {
            myModel = new Model(id);
            return this;
        }

        public ModelBuilder WithName(string name)
        {
            myModel.Name = name;
            return this;
        }

        public ModelBuilder WithAge(int age)
        {
            myModel.Age = age;
            return this;
        }

        public ModelBuilder WithComplexLogic(int data)
        {
            myModel.ProcesData(data)
            return this;
        }

        public Model Build()
        {
            return myModel;
        }
    }

I can use it like this

var modelBuilder = new ModelBuilder<Model>();
modelBuilder.WithName("Name");
modelBuilder.WithAge(30);
modelBuilder.WithComplexLogic(42);
var model = modelBuilder.Build();

Is it possible to create a more generic version for this so I can use it for other classes without creating new methods for setting simple properties values? I was thinking something with lambda syntax for Name and Age, but ComplexLogic() stays the same.

var modelBuilder = new ModelBuilder<Model>();
modelBuilder.WithProperty(x => x.Name = "Name");
modelBuilder.WithProperty(x => x.Age = 30);
modelBuilder.WithComplexLogic(42);
var model= modelBuilder.Build();

CodePudding user response:

A quick way to do this is to create an Initialize method like this:

public partial class ModelBuilder
{
    private Model myModel;

    // ...

    public ModelBuilder Initialize(Action<Model> initModel)
    {
        initModel(myModel);
        return this;
    }

    // ...
}

You can call the method and initialize several properties of the model like this:

var modelBuilder = new ModelBuilder<Model>();
modelBuilder.Initialize(model => 
{
  model.Name = "Name"; 
  model.Age = 30;
  // ...
});
modelBuilder.WithComplexLogic(42);
var model= modelBuilder.Build();

If you want to do it property by property, you can use an Expression<Func<Model, T>>, e.g.

public partial class ModelBuilder
{
    private Model myModel;

    // ...

    public ModelBuilder WithProperty<T>(Expression<Func<Model, T>> propExpr, T value)
    {
        MemberExpression member = (MemberExpression)propExpr.Body;
        PropertyInfo propInfo = (PropertyInfo)member.Member;
        propInfo.SetValue(myModel, value);        
        return this;
    }

    // ...
}

The method receives a lambda expression as parameter that determines the property; it analyzes the lambda expression and assigns the property value using the PropertyInfo.SetValue method.

  • Related