/// <summary> /// Creates a <see cref="WithCSharpExpression"/> that represents a with expression. /// </summary> /// <param name="object">The expression representing the object to clone and mutate.</param> /// <param name="clone">The method used to clone the object.</param> /// <param name="initializers">The initializers used to mutate the cloned object.</param> /// <returns>The created <see cref="WithCSharpExpression"/>.</returns> public static WithCSharpExpression With(Expression @object, MethodInfo clone, IEnumerable <MemberInitializer> initializers) { RequiresNotNull(@object, nameof(@object)); RequiresNotNull(initializers, nameof(initializers)); var initializersCollection = initializers.ToReadOnly(); ValidateWithReceiverAndInitializers(@object, initializersCollection, requiresCanAssign: true); if (@object.Type.IsValueType) { if (clone != null) { throw Error.WithExpressionCannotHaveCloneForValueType(@object.Type); } } else { clone ??= @object.Type.GetNonGenericMethod("Clone", BindingFlags.Public | BindingFlags.Instance, Type.EmptyTypes); if (clone == null) { throw Error.WithExpressionShouldHaveClone(@object.Type); } ValidateMethodInfo(clone); if (clone.IsStatic) { throw Error.CloneMethodMustNotBeStatic(clone.Name); } if (!clone.DeclaringType.IsAssignableFrom(@object.Type)) { throw LinqError.NotAMemberOfType(clone.Name, @object.Type); } if (clone.GetParametersCached().Length != 0) { throw Error.CloneMethodShouldHaveNoParameters(clone.Name); } if (!HasReferenceConversion(clone.ReturnType, @object.Type)) { throw Error.CloneMethodShouldReturnCompatibleType(clone.Name, @object.Type); } } return(new WithCSharpExpression(@object, initializersCollection, clone, members: null)); }