diff --git a/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj b/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
index b1a32abb74..a0871f1848 100644
--- a/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
+++ b/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
@@ -404,6 +404,7 @@
+
diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertToInitializer/ConvertInitializerToExplicitInitializationsAction.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertToInitializer/ConvertInitializerToExplicitInitializationsAction.cs
new file mode 100644
index 0000000000..1dbb82c9d0
--- /dev/null
+++ b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertToInitializer/ConvertInitializerToExplicitInitializationsAction.cs
@@ -0,0 +1,208 @@
+//
+// ConvertInitializerToExplicitInitializationsAction.cs
+//
+// Author:
+// Simon Lindgren
+//
+// Copyright (c) 2012 Simon Lindgren
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace ICSharpCode.NRefactory.CSharp.Refactoring
+{
+ [ContextAction("Convert to explicit initializers",
+ Description = "Converts an object or collection initializer to explicit initializations.")]
+ public class ConvertInitializerToExplicitInitializationsAction : ICodeActionProvider
+ {
+ #region ICodeActionProvider implementation
+
+ public IEnumerable GetActions(RefactoringContext context)
+ {
+ var codeAction = GetActionForVariableInitializer(context);
+ if (codeAction != null) {
+ yield return codeAction;
+ yield break;
+ }
+ codeAction = GetActionForAssignmentExpression(context);
+ if (codeAction != null) {
+ yield return codeAction;
+ yield break;
+ }
+ }
+
+ public CodeAction GetActionForVariableInitializer(RefactoringContext context)
+ {
+ var variableInitializer = context.GetNode();
+ if (variableInitializer == null)
+ return null;
+ var declaration = variableInitializer.Parent as VariableDeclarationStatement;
+ if (declaration == null)
+ return null;
+ if (variableInitializer.Initializer.IsNull)
+ return null;
+ var objectCreateExpression = variableInitializer.Initializer as ObjectCreateExpression;
+ if (objectCreateExpression == null)
+ return null;
+ var converter = new InitializerConversionVisitor(context);
+ Expression finalExpression;
+ var statements = converter.ConvertInitializer(objectCreateExpression, out finalExpression);
+ if (statements.Count > 0) {
+ return new CodeAction(context.TranslateString("Convert to explicit initializers"), script => {
+ foreach (var statement in statements) {
+ script.InsertBefore(declaration, statement);
+ }
+ script.Replace(variableInitializer.Initializer, finalExpression);
+ });
+ }
+ return null;
+ }
+
+ public CodeAction GetActionForAssignmentExpression(RefactoringContext context)
+ {
+ var assignmentExpression = context.GetNode();
+ if (assignmentExpression == null)
+ return null;
+ var expressionStatement = assignmentExpression.Parent as ExpressionStatement;
+ if (expressionStatement == null)
+ return null;
+ var objectCreateExpression = assignmentExpression.Right as ObjectCreateExpression;
+ if (objectCreateExpression == null)
+ return null;
+ var converter = new InitializerConversionVisitor(context);
+ Expression finalExpression;
+ var statements = converter.ConvertInitializer(objectCreateExpression, out finalExpression);
+ if (statements.Count > 0) {
+ return new CodeAction(context.TranslateString("Convert to explicit initializers"), script => {
+ foreach (var statement in statements) {
+ script.InsertBefore(expressionStatement, statement);
+ }
+ script.Replace(assignmentExpression.Right, finalExpression);
+ });
+ }
+ return null;
+ }
+ #endregion
+
+ class InitializerConversionVisitor : DepthFirstAstVisitor
+ {
+ RefactoringContext context;
+ IList statements;
+ NamingHelper namingHelper;
+
+ public InitializerConversionVisitor(RefactoringContext context)
+ {
+ this.context = context;
+ namingHelper = new NamingHelper(context);
+ }
+
+ AstType GetDeclarationType(AstType type)
+ {
+ AstType declarationType;
+ if (context.UseExplicitTypes) {
+ declarationType = type.Clone();
+ } else {
+ declarationType = new SimpleType("var");
+ }
+ return declarationType;
+ }
+
+ public IList ConvertInitializer(ObjectCreateExpression initializer, out Expression finalExpression)
+ {
+ statements = new List();
+
+ finalExpression = initializer.AcceptVisitor(this, null);
+
+ return statements;
+ }
+
+ public override Expression VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, Expression data)
+ {
+ var creationType = objectCreateExpression.Type.Clone();
+
+ var parameters = objectCreateExpression.Arguments.Select(arg => arg.Clone());
+ var newCreation = new ObjectCreateExpression(creationType, parameters);
+ if (objectCreateExpression.Initializer.IsNull) {
+ return newCreation;
+ } else {
+ AstType declarationType = GetDeclarationType(objectCreateExpression.Type);
+ var name = namingHelper.GenerateVariableName(objectCreateExpression.Type);
+ var variableInitializer = new VariableDeclarationStatement(declarationType, name, newCreation);
+ statements.Add(variableInitializer);
+
+ var identifier = new IdentifierExpression(name);
+ base.VisitObjectCreateExpression(objectCreateExpression, identifier);
+
+ return identifier;
+ }
+ }
+
+ public override Expression VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression, Expression data)
+ {
+ if (!(arrayInitializerExpression.Parent is ArrayInitializerExpression)) {
+ return base.VisitArrayInitializerExpression(arrayInitializerExpression, data);
+ }
+ // this a tuple in a collection initializer
+ var arguments = arrayInitializerExpression.Elements.Select(element => element.AcceptVisitor(this, null).Clone());
+ var method = new MemberReferenceExpression {
+ Target = data.Clone(),
+ MemberName = "Add"
+ };
+ var statement = new ExpressionStatement(new InvocationExpression(method, arguments));
+ statements.Add(statement);
+
+ return null;
+ }
+
+ public override Expression VisitNamedExpression(NamedExpression namedExpression, Expression data)
+ {
+ var member = new MemberReferenceExpression {
+ Target = data.Clone(),
+ MemberName = namedExpression.Name
+ };
+ var expression = namedExpression.Expression.AcceptVisitor(this, member);
+ if (expression != null) {
+ var statement = new ExpressionStatement {
+ Expression = new AssignmentExpression {
+ Left = member,
+ Right = expression.Clone()
+ }
+ };
+ statements.Add(statement);
+ }
+
+ return null;
+ }
+
+ protected override Expression VisitChildren(AstNode node, Expression data)
+ {
+ // Most expressions should just be used as-is, and
+ // a) need not be visited
+ // b) only return themselves
+ if (node is Expression && !(node is ObjectCreateExpression || node is ArrayInitializerExpression || node is NamedExpression)){
+ return (Expression)node;
+ }
+ return base.VisitChildren(node, data);
+ }
+ }
+ }
+}
+
diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ConvertToInitializer/ConvertInitializerToExplicitIntializationsTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ConvertToInitializer/ConvertInitializerToExplicitIntializationsTests.cs
new file mode 100644
index 0000000000..b507069cb0
--- /dev/null
+++ b/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ConvertToInitializer/ConvertInitializerToExplicitIntializationsTests.cs
@@ -0,0 +1,141 @@
+//
+// ConvertInitializerToExplicitIntializationsTests.cs
+//
+// Author:
+// Simon Lindgren
+//
+// Copyright (c) 2012 Simon Lindgren
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using NUnit.Framework;
+using ICSharpCode.NRefactory.CSharp.Refactoring;
+
+namespace ICSharpCode.NRefactory.CSharp.CodeActions
+{
+ [TestFixture]
+ public class ConvertInitializerToExplicitIntializationsTests : ContextActionTestBase
+ {
+ string baseText = @"
+class TestClass
+{
+ public string Property { get; set; }
+
+ public TestClass Nested { get; set; }
+
+ void F ()
+ {
+ ";
+
+ [Test]
+ public void SingleLevelObjectIntializer ()
+ {
+ Test(baseText + @"
+ var variable = new Test$Class () {
+ Property = ""Value""
+ };
+ }
+}", baseText + @"
+ var testClass = new TestClass ();
+ testClass.Property = ""Value"";
+ var variable = testClass;
+ }
+}");
+ }
+
+ [Test]
+ public void ObjectCreateExpressionWithoutObjectInitializer ()
+ {
+ Test(baseText + @"
+ var variable $= new System.Collection.Generic.List () {
+ new TestClass () {
+ Property = ""One"",
+ Nested = new TestClass ()
+ }
+ };
+ }
+}", baseText + @"
+ var list = new System.Collection.Generic.List ();
+ var testClass = new TestClass ();
+ testClass.Property = ""One"";
+ testClass.Nested = new TestClass ();
+ list.Add (testClass);
+ var variable = list;
+ }
+}");
+ }
+
+ [Test]
+ public void SingleLevelObjectIntializerToExistingVariable ()
+ {
+ Test(baseText + @"
+ var variable = new TestClass ();
+ variable = new Test$Class () {
+ Property = ""Value""
+ };
+ }
+}", baseText + @"
+ var variable = new TestClass ();
+ var testClass = new TestClass ();
+ testClass.Property = ""Value"";
+ variable = testClass;
+ }
+}");
+ }
+
+ [Test]
+ public void SingleLevelCollectionIntializer ()
+ {
+ Test(baseText + @"
+ var variable $= new System.Collection.Generic.Dictionary () {
+ {""Key1"", new TestClass { Property = ""Value1"", Nested = { Property = ""Value1b"" }}}
+ };
+ }
+}", baseText + @"
+ var dictionary = new System.Collection.Generic.Dictionary ();
+ var testClass = new TestClass ();
+ testClass.Property = ""Value1"";
+ testClass.Nested.Property = ""Value1b"";
+ dictionary.Add (""Key1"", testClass);
+ var variable = dictionary;
+ }
+}");
+ }
+
+ [Test]
+ public void CollectionOfIntializers ()
+ {
+ Test(baseText + @"
+ var variable $= new System.Collection.Generic.Dictionary () {
+ {""Key1"", new TestClass { Property = ""Value1"", Nested = { Property = ""Value1b"" }}}
+ };
+ }
+}", baseText + @"
+ var dictionary = new System.Collection.Generic.Dictionary ();
+ var testClass = new TestClass ();
+ testClass.Property = ""Value1"";
+ testClass.Nested.Property = ""Value1b"";
+ dictionary.Add (""Key1"", testClass);
+ var variable = dictionary;
+ }
+}");
+ }
+
+ }
+}
+
diff --git a/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj b/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj
index 4f0cfee082..5de6deb2fb 100644
--- a/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj
+++ b/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj
@@ -297,6 +297,7 @@
+