0

I'm trying to figure out a way to build something like this using CodeDom

public System.Collections.Generic.Dictionary<string, string> Attributes
{
    get
    {
        return new System.Collections.Generic.Dictionary<string, string>()
        {
            {"firstkey", "first value"},
            {"second", "second value"},
            {"third", "third value"}
        };
    }
}

I did read this but it didn't really get me where I wanted to, http://msdn.microsoft.com/en-us/library/system.codedom.codetypeparameter.aspx

I did this

Type myType = typeof (System.Collections.Generic.Dictionary<string, string>);
string dictionaryTypeName = myType.FullName;

CodeTypeReference dictionaryType = new CodeTypeReference(dictionaryTypeName);

var abc = new CodeVariableDeclarationStatement(
    dictionaryType, "dict2",
    new CodeObjectCreateExpression(
        dictionaryType, new CodeSnippetExpression(@"{""firstkey"", ""first value""}")
        )
    );

property.GetStatements.Add(abc);

It generates this

public Dictionary<object, object> Attributes
{
    get
    {
        Dictionary<string, string> dict2 = new Dictionary<string, string>({"firstkey", "first value"});
    }
}

Anyone who built something similar?

Eric Herlitz
  • 25,354
  • 27
  • 113
  • 157

2 Answers2

1

I did have to use .add instead of adding the values as parameters to the constructor.

if (type == typeof(Dictionary<string, string>))
{
    string variableName = "dict";

    CodeVariableDeclarationStatement codeVariableDeclarationStatement = new CodeVariableDeclarationStatement(new CodeTypeReference(type.FullName), variableName,
            new CodeObjectCreateExpression(type)
    );

    property.GetStatements.Add(codeVariableDeclarationStatement);
    property.GetStatements.Add(AddPropertyValues(new CodeSnippetExpression(string.Format(@"""{0}"", ""{1}""", "a", "xx xx1")), variableName));
    property.GetStatements.Add(AddPropertyValues(new CodeSnippetExpression(string.Format(@"""{0}"", ""{1}""", "b", "xx xx2")), variableName));
    property.GetStatements.Add(AddPropertyValues(new CodeSnippetExpression(string.Format(@"""{0}"", ""{1}""", "c", "xx xx3")), variableName));

    property.GetStatements.Add(new CodeMethodReturnStatement(new CodeSnippetExpression(variableName)));
}

static CodeStatement AddPropertyValues(CodeExpression exp, string variableReference)
{
    return new CodeExpressionStatement(
        new CodeMethodInvokeExpression(
            new CodeMethodReferenceExpression(
                new CodeTypeReferenceExpression(new CodeTypeReference(variableReference)),
                    "Add"),
                        new CodeExpression[]{
                            exp,
                                }));
}

Generates this

public System.Collections.Generic.Dictionary<string, string> Attributes
{
    get
    {
        System.Collections.Generic.Dictionary<string, string> dict = new System.Collections.Generic.Dictionary<string, string>();
        dict.Add("a", "xx xx1");
        dict.Add("b", "xx xx2");
        dict.Add("c", "xx xx3");
        return dict;
    }
}

fair enough!

Eric Herlitz
  • 25,354
  • 27
  • 113
  • 157
1

If you want to use the initialization instead of using the Add method, you have to go the Snippet way for the constructor's call, too. This can be more difficult if you don't want to write the type name in a constant string. In this case you can create a call to the parameterless constructor, use the CSharpCodeProvider to obtain the string that represent the constructor's call, throw away the final parentheses and concatenate the initialization snippet. The code would be something like this and generates the required code:

        CSharpCodeProvider codeProvider = new CSharpCodeProvider();
        CodeGeneratorOptions options = new CodeGeneratorOptions();
        options.IndentString = "   ";
        options.BracingStyle = "C";

        Type myType = typeof(System.Collections.Generic.Dictionary<string, string>);
        string dictionaryTypeName = myType.FullName;

        CodeTypeReference dictionaryType = new CodeTypeReference(dictionaryTypeName);

        // here you create the CodeobjectCreateExpression in order to obtain the string with the name of the type
        StringWriter sw = new StringWriter();
        CodeObjectCreateExpression createExpr = new CodeObjectCreateExpression(dictionaryType);
        codeProvider.GenerateCodeFromExpression(createExpr, sw, options);
        string creationCode = sw.ToString();
        // throw away the final ()
        creationCode = creationCode.Substring(0, creationCode.Length - 2);
        // add initialization
        creationCode = creationCode + @"{{""firstkey"", ""first value""}, {""secondkey"", ""second value""}, {""thirdkey"", ""third value""}}";
        CodeMethodReturnStatement retVal = new CodeMethodReturnStatement(new CodeSnippetExpression(creationCode));
        property.GetStatements.Add(retVal);
Francesco Baruchelli
  • 7,320
  • 2
  • 32
  • 40