1

I need to create an immutable object but it requires several parameters to work like:

class FooRepo
{
    public string ConnectionStringName { get; }
    public string SchemaName { get; }
    public string TableName { get; }
    public Dictionary<string, int> ColumnLengths { get; }
    public Dictionary<Type, SqlDbType> TypeMappings { get; }

    // some queries...
    public IEnumerable<string> GetStrings(object param1) { ... }
}

I find there are too many parameters to pass them all via the constructor (I might add more later).

The idea of locking the object after it's been setup doesn't sound good either.

I thought about creating a FooBuilder but this would only hide a huge constructor.

The only resonable solution I can think of is to define default values for some properties like ColumnLengths and TypeMappings and allow the user to override/customize them by deriving from the original class.

What would you say? Or maybe there are better ways for such a task?

  • 3
    builder pattern appears to be perfect match for this, I find it hard to figure what could be wrong with FooBuilder. (possible duplicate: Class with members that are mutable during creation but immutable afterwards) – gnat Jun 25 '16 at 19:43
  • 1
    @gnat you're right, this looks like an exact duplicate of the other question. I just couldn't ask it that way to be able to find it ;-) thx – t3chb0t Jun 25 '16 at 19:55
  • sounds to me like your code is speaking! "help! I'm too big! I'm going to blow up! please separate me into smaller more cohesive types!" – sara Jun 25 '16 at 20:12
  • @kai even if I move some of the properties into a new object like FooRepoProperties the problem will remain the same. – t3chb0t Jun 25 '16 at 21:51
  • "I find there are too many parameters to pass them all via the constructor." My many is too many? What is stopping you? – paparazzo Jun 26 '16 at 6:42
2

Assumed your class is not "too large" (which you should check first), instead of having a huge constructor argument list in FooRepo, you can pass the values in by utilizing a mutable DTO object as a form of "helper object". This might be a class FooRepoDTO, or when you follow the builder pattern, it could be the FooRepoBuilder itself (which must provide access to all the data passed in by the "Set..." methods.

  • I think I'll mix them and I use a builder to setup the DTO object and give it internal setters so that the builder can set the values but later it'll act as immutable. – t3chb0t Jun 25 '16 at 20:49
8

You pass them in via the constructor. If that means your constructor is too large, then maybe your giant class shouldn't be so giant.

There are very few things in the world that have 5+ independent, but cohesive elements.

1

OK, I think I got it but it's a little bit different then the origial builder pattern. If the builder is nested inside the immutable object it then can still access its properties and set them even if they remain private to the actual object:

class Foo
{
    public Foo() {} 

    public string Bar { get; private set; }

    public string Qux { get; }

    public class Builder
    {
        private Foo _foo = new Foo();
        private Builder() {}

        public static Builder Create() 
        {
            return new Builder();
        }

        public Builder Bar(string bar) 
        {
            _foo.Bar = bar;
            return this;
        }

        public Foo ToFoo()
        {
            return new Foo() 
            {
                Bar = _foo.Bar
            };
        }
    }
}

Usage:

var foo = Foo.Builder.Create().Bar("baz").ToFoo();
var bar = foo.Bar;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.