Autofac IEnumerable resolve cause multiple construction

515 views Asked by At

I have this registration:

 builder.RegisterAssemblyTypes(assembly)
            .AsClosedTypesOf(typeof(IBusinessRule<>))
            .AsImplementedInterfaces()
            .SingleInstance();

And I resolve it this way:

 using (var scope = Container.BeginLifetimeScope())
 {
        var rules = Container.Resolve<IEnumerable<IBusinessRule<T>>>();

        var result = rules.Select(x => x.IsValid(t));

        if (result.Any(x => !x.Successful))
        {
            var msg = string.Join(Environment.NewLine, result.Where(x => !x.Successful).Select(x => x.Message));

            return new OperationResultBase()
            {
                Message = msg,
                Successful = false,
                Operation = System.Reflection.MethodBase.GetCurrentMethod().Name
            };
        }
        else
        {
            return new OperationResultBase(true);
        }
  }

The problem lies in this line:

var result = rules.Select(x => x.IsValid(t));

With that resolve, the classes that implement the IBusinessRule<T> are called once per each result variable enumeration.

If I call ToList() on result, then everything is OK and would be called only once.

Is calling ToList() a correct approach or the registration has some problems and should be changed?

1

There are 1 answers

3
Sriram Sakthivel On

Is calling ToList() a correct approach or the registration has some problems and should be changed?

No, Nothing wrong with your registration. This is the lazy evaluation property of Linq.

In fact it has nothing to do with the autofac. A normal lazy linq query would exactly behave the same way as you see.

If you need the materialized result, you need to call ToList or ToArray. Otherwise, query will be evaluated on each enumeration (for example via foreach);