none
How to create List with constructor without explicit types? RRS feed

  • Question

  • Hi,

    Its better to explain my question using some code:

    Type listType = Type.GetType("System.Collections.Generic.List`1[[System.String, mscorlib]]");
    string[] strArray = { "Ronnie", "Jack", "Lori", "Max", "Tricky" };
    
    // How do I create these parameters from a type-name?
    IEnumerable<string> parameters = strArray;
    object myListOfStrings = Activator.CreateInstance(listType, parameters);
     
    This all works but I have to explicitly create the IEnumerable in order to get it to work. Cant I somehow create the parameter for List<string> constructor only from type-name? I have to create this object entirely from configuration xml...

    --


    • Moved by OmegaManModerator Wednesday, June 24, 2009 10:13 AM Related to Linq (From:Visual C# General)
    Thursday, June 18, 2009 2:28 PM

All replies

  • I just tried something similar passing strArray directly instead of parameters and it worked for me. But I am not doing the exact same code as this.

    I will try to update my example to more closely look like yours and try again.
    www.insteptech.com
    We are volunteers and ask only that if we are able to help you, that you mark our reply as your answer. THANKS!
    Thursday, June 18, 2009 5:59 PM
  • OK, when I first tried this, I used an existing type I had with an appropriate constructor.

    I then tried it with your List<string> type and its constructor requires an IEnumerable. That is why you are getting an error if you don't convert the list to IEnumerable.

    So if you wanted this to be completely smart, you would have to get the constructor parameter type and then convert your string array to that type. Make sense?
    www.insteptech.com
    We are volunteers and ask only that if we are able to help you, that you mark our reply as your answer. THANKS!
    Thursday, June 18, 2009 6:03 PM
  • This also works, but I bet that does not help:

    object myListOfStrings = Activator.CreateInstance(listType, (IEnumerable<string>)strArray);

    www.insteptech.com
    We are volunteers and ask only that if we are able to help you, that you mark our reply as your answer. THANKS!
    Thursday, June 18, 2009 6:05 PM
  • I'm not certain exactly what you need here because if you can't hard-code the IEnumerable, I don't quite understand how you could hard-code the string array. But if you want something generic, this worked for me:

            private void WorkWithReflection<T>(T[] myArray)
            {
                string typeName = myArray[0].GetType().FullName;
                Type listType = Type.GetType("System.Collections.Generic.List`1[[" + typeName + ", mscorlib]]");
    
                object myListOfStrings = Activator.CreateInstance(listType, myArray);
            }
    This creates a List<T> where T can be any type. NOTE: I did not add the appropriate validation to ensure that the incoming array has at least one value.

    To call this method, you could use this code:
                string[] strArray = { "Ronnie", "Jack", "Lori", "Max", "Tricky" };
                WorkWithReflection(strArray);
    Hope this at least gives you some ideas to get closer to what you need.

    www.insteptech.com
    We are volunteers and ask only that if we are able to help you, that you mark our reply as your answer. THANKS!
    Thursday, June 18, 2009 6:18 PM
  • Hi DeborahK,

    Thanks for your posts, really appreciated. I think the point here is that I probably cant do what I want - express all types and all parameters as text. Imagine that I want to invoke "Activator.CreateInstance(type, parameters);" where both "type" and "parameters" are created from xml definition. The Type is easy but the parameter list isnt.

    Imagine that you have a class that in its constructor takes 1 int32 parameter. This means that I can create all arguments for "Activator.CreateInstance" like this:


    public class Consumer
    {
        public void Test()
        {
            object paramInput = "5";
            Type typeToActivate = Type.GetType("SomeNamespace.SimpleClass");
            Type typeOfParameter = Type.GetType("System.Int32");
    
            object param = Convert.ChangeType(paramInput, typeOfParameter);
    
            object newSimpleClass = Activator.CreateInstance(typeToActivate, param);
        }
    }
    
    public class SimpleClass
    {
        public int Some { get; set; }
    
        public SimpleClass(int something)
        {
            this.Some = something;
        }
    }
      
    This would work as expected. But things are not that clear to me if the parameters arent simple types like strings or valuetypes. If the above is compared to my original example, the problem is that I cant figure out how to express "IEnumerable<string>" using only xml (text strings).

    I kinda know this isnt possible - but I might be unaware of some functionality - thus this thread.

    --
    Friday, June 19, 2009 7:22 AM
  • Hi,

    Could you be more specific about the scenario?
    What is the content of the xml file ? What instances do you want to get?

    Harry
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Wednesday, June 24, 2009 6:09 AM
  • Hi,

    Could you be more specific about the scenario?
    What is the content of the xml file ? What instances do you want to get?

    Harry
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.

    Hi,

    Yes, Im writing a serializer for expression trees using System.Xml.Linq. The problem arises for example when dealing with "Expressions.NewExpression" types. If we are talking about a new List<string> for example, this expression must be serialized with a constructor that defines parameters and arguments. If the List<string> isn't empty then the argument must be serialized as a constant expression of type "System.String[]" and the value = ?

    My trouble is that value. How do I express this so that the constructor upon de-serialization creates the list with the proper content. My solution sofar has been to serialize the List (or other objects) to Xml using the XmlSerializer and then store this in the ConstantExpression value XCData.

    This all works well but it isnt as elegant as I would like it to be. I have no particular experience with other forms of serialization (non-xml) so I wondered if I somehow could express (serialize) objects in some other form that doesnt require actual deserialization. Hope you get the meaning here :) . However this is generally speaking. I only need this for rather simple objects - like ILists. So my original question meant: Can I sonehow express an IList data - as text - in some form that is directly acceptable by one of the IList constructors.

    -- 



     










    Wednesday, June 24, 2009 9:53 AM
  • Hi,

    I still can not get it.
    Could you please post the content of the xml file , and the result that is going to be generated?

    Harry
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Wednesday, June 24, 2009 10:02 AM
  • Hi,

    I still can not get it.
    Could you please post the content of the xml file , and the result that is going to be generated?

    Harry
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.

    Hi, my apologies for the late answer but I have been away a couple of days on this particular project. Anyways, here is an xml node that represent the serialization operand of a UnaryExpression - in this case a NewExpression:

    <NewExpression NodeType="New">
                      <Constructor MemberType="Constructor" MethodName=".ctor">
                        <DeclaringType>
                          <Type Name="System.Collections.Generic.List`1">
                            <Type Name="System.String" />
                          </Type>
                        </DeclaringType>
                        <Parameters>
                          <Parameter Name="collection">
                            <Type>
                              <Type Name="System.Collections.Generic.IEnumerable`1">
                                <Type Name="System.String" />
                              </Type>
                            </Type>
                          </Parameter>
                        </Parameters>
                      </Constructor>
                      <Arguments>
                        <ConstantExpression NodeType="Constant">
                          <Value><![CDATA[<?xml version="1.0" encoding="utf-8"?>
    <ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <string>para1</string>
      <string>para2</string>
    </ArrayOfString>]]></Value>
                          <Type>
                            <Type Name="System.String[]" />
                          </Type>
                        </ConstantExpression>
                      </Arguments>
                      <Members />
                      <Type>
                        <Type Name="System.Collections.Generic.List`1">
                          <Type Name="System.String" />
                        </Type>
                      </Type>
                    </NewExpression>
     
    My thoughts is concerning the "Value" element of the ConstantExpression. As you can see this ConstantExpression is the argument for the constructor definition. What I asked about was some way to express this constant value so that it can be used as a direct input for the constructor. So that the "Value" element of the ConstantExpression is usable as an argument of type IEnumerator<string>. 

    As you can see, I have solved this in letting the value be a CData section which contains xml that is run through a XmlSerializer which outputs a List. This is ok, but I have only experience in serializing Xml - so I thought that there perhaps was some other (and more clever/faster) way to accomplish this.

    I know that without any bigger picture, it is hard to comment on this but I cant be more precise because I have absolutely no idea of what any alternative might look like. Though I have been spending some time reading up on serialization techniques and it seems that there arent that many options (e.g. Xml, Binary). So perhaps I'm looking for something that just isnt there...

    -- 











     
    Thursday, July 2, 2009 1:14 PM