Cast object to List<object> - c#

For some reasons outside of my control a method of mine needs to be defined to accept one parameter of type object. But i know that the value of this parameter is actually of type List with a generic parameter unknown to me.
I am trying to cast this object to List<object>, but have no idea how to do this without knowing what the exact generic parameter is.
I would like to do something like this:
public static List<object> ConvertToList(object input)
{
if (input.GetType().GetGenericTypeDefinition().IsAssignableFrom(typeof(List<>)))
{
//Of course this does not work, because input might for example be of type List<string>
return (List<object>) input;
}
else
{
return null;
}
}
I know that if I had List<T> instead of object input, it would be quite easy by using:
return input.Cast<object>()
but unfortunately i'm stuck with the object parameter. Any idea how i could solve this problem?

You can't cast it, but you can project it onto a list using IEnumerable and Cast. This will give you a new instance of List<object>. You won't be able to modify the old list but you can work with the new one and modify its elements.
object obj = new List<Whatever>();
List<object> list = ((IEnumerable)obj).Cast<object>().ToList();

Related

Create list of generic object at runtime

I have object of some type known at runtime and I read and deserialize this object from database. It works. Now I would like to add it to some list:
private static List<T> generateList<T>()
{
List<T> lst = new List<T>();
return lst;
}
private void readObjects(System.Type objType)
{
var methodInfo = typeof(My.Serializator).GetMethod("DeserializeDb");
var genericMethod = methodInfo.MakeGenericMethod(objType1);
List<curType> currentList= generateList<curType>();
// ...read stream from database and convert it to object
while (_rs.Read())
{
var _objItem = genericMethod.Invoke(null, new[] { _streamedData });
currentList.Add(_objItem);
}
}
It won't work. The error is:
curType is a variable but is used like a type.
If I change list to:
List<object> currentList = new List<object>();
it will work. But can i do this with generics(T) instead of object type?
You can easly create type of list you want via Activator, then cast to IList and use it:
private IList readObjects(System.Type objType)
{
var listType = typeof(List<>).MakeGenericType(curType);
var list = (IList)Activator.CreateInstance(listType);
// ...
while (_rs.Read())
{
// ...
list.Add(_objItem);
}
}
list will be instance of List<YorActualType>.
Update
When you declaring your method with generic arguments, it assumes you provide type info during compile time. Otherwise you need to use reflection.
Since you providing type info in run time (curType can hold any type info), compiler does not know what exactly type will be used, and you cannot declare your method to return something concrete. Only abstractions allowed.
Let's me show it on slightly insane but demonstrative example:
var types = new [] { typeof(int), typeof(string) };
var rand = new Random();
var list = readObjects(types[rand.Next(0,2)];
Until the very last moment even you will not know what exactly type of list will be created. Compiler does not know too. Compiler will never know what exactly type should be used if you not provide him with you types. When you use Type it only tells compiler that some regular parameter with type Type will be passed into the method in run time. There is no data to infer a type during compile time. That data can be passed only via generic type parameters.
So, there is several ways you can follow:
Provide exact types you need at compile time
private List<T> readObjects<T>()
{
var objType = typeof(T);
var list = new List<T>();
// rest of code....
}
Use reflection and base types
private IList readObjects(Type objType)
{
// rest of code with Activator and so on
}
And later usage depends on your needs.
If you know what type you going to use, simply convert:
var list = (IList<MyType>)readObjects(typeof(myType));
But I guess in that case better use way #1 with generic argument.
Otherwise you going to use reflection. Or some base classes, interfaces and so on. It depends on what exactly task you going to solve.
P.S. You can read more about generic types on MSDN.

C# reflection dictionary

say I have this code:
Dictionary<String, String> myDictionary = new Dictionary<String, String>();
Type[] arguments = myDictionary.GetType().GetGenericArguments();
In my program, myDictionary it's of unknown types (it's an object returned from a deserialized XML), but for the purpose of this question, they are string. I want to create something like this:
Dictionary<arguments[0],arguments[1]> mySecondDictionary = new Dictionary<arguments[0],arguments[1]>();
Obviously, it doesn't work.
I searched on MSDN, and I saw they are using the Activator class, but I don't get it.
Maybe somebody more advanced, could help me a little.
You can use the activator class like you mentioned in order to create objects from given types. The MakeGenericType method allows you to specify an array of Types as the parameters for generic objects, which is what you were trying to simulate.
Dictionary<String, String> myDictionary = new Dictionary<String, String>();
Type[] arguments = myDictionary.GetType().GetGenericArguments();
Type dictToCreate = typeof(Dictionary<,>).MakeGenericType(arguments);
var mySecondDictionary = Activator.CreateInstance(dictToCreate);
The code above is essentially pointless as you know that the dictionary is String,String beforehand but assuming you have a way of detecting the required types elsewhere during runtime, you can use the last two lines to instantiate a dictionary of that type.
There is a problem with this approach.
I will try my best to explain it.
I wrote a program which first serializes a class into XML, then deserializes it back.
Basically, the class it's a generic one, and it contains a List(the same type with the class).
So, the type of the class could be anything, starting from simple types, like string, int, etc to more complex classes, like for example a book class, or a person. After using the XmlSerializer.Deserialize method, and getting the object, I should use Reflection to reconstruct back the object, and access the list. And I can't do it that way.
So, if I have something like:
Type classToCreate = typeof(classToBeSerialized<>).MakeGenericType(arguments);
var reconstructedClass = Activator.CreateInstance(classToCreate);
where classToBeSerialized it's the supposed class(which has the list which I have spoken of), and returnedObject it's the object returned from XmlSerializer.Deserialize, I want to access the list like this:
((reconstructedClass)returnedObject).lista
Basically, I'm using reflection to cast the object to it's source.
I know this is an old thread, but I just needed something similar, and decided to show it, (you know for google).
this is basicly a rewrite of the answer by #user2536272
public object ConstructDictionary(Type KeyType, Type ValueType)
{
Type[] TemplateTypes = new Type[]{KeyType, ValueType};
Type DictionaryType = typeof(Dictionary<,>).MakeGenericType(TemplateTypes);
return Activator.CreateInstance(DictionaryType);
}
public void AddToDictionary(object DictionaryObject, object KeyObject, object ValueObject )
{
Type DictionaryType = DictionaryObject.GetType();
if (!(DictionaryType .IsGenericType && DictionaryType .GetGenericTypeDefinition() == typeof(Dictionary<,>)))
throw new Exception("sorry object is not a dictionary");
Type[] TemplateTypes = DictionaryType.GetGenericArguments();
var add = DictionaryType.GetMethod("Add", new[] { TemplateTypes[0], TemplateTypes[1] });
add.Invoke(DictionaryObject, new object[] { KeyObject, ValueObject });
}

CreateDelegate On Extension Method

I have a class with an IList readonly property. I have created a simple extension method, AddCSV, to add multiple items to that list. I want to create an action delegate to populate the list via the extension method. So far, I have
private Action<TListPropertyContainer, TDataValue> CreateListPropertySetter<TListPropertyContainer, TDataValue>(string listName)
{
var list = typeof(TListPropertyContainer).GetProperty(listName);
var method = typeof(Extensions).GetMethod("AddCSV");
return (Action<TListPropertyContainer, TDataValue>)Delegate.CreateDelegate(typeof(Action<TListPropertyContainer, TDataValue>), list, method);
}
but obviously this isn't working!
I am aware that there are other options. For example
a) I could inherit the list into my own customer class and add the AddCSV there
b) I could make items property read/write and set a fully populated list into my class
I'd be grateful if someone could correct me.
Many thx
Simon
There are two main problems.
You are trying to invoke the method on a PropertyInfo, not a list. To get the value of the property you would need to make a call to GetValue()
The call to GetMethod() doesn't specify binding flags. I suspect it might work better with GetMethod("AddCSV", BindingFlags.Public | BindingFlags.Static).
That being said, why are you instantiating it reflectively when you know the type and the method beforehand? It seems like you could just do:
private Action<TListPropertyContainer, TDataValue> CreateListPropertySetter<TListPropertyContainer, TDataValue>(string listName)
{
var propertyInfo = typeof(TListPropertyContainer).GetProperty(listName);
return (container,value) => {
var list = (IList<TDataValue>)propertyInfo.GetValue(container,null);
list.AddCSV(list);
};
}
If I am making incorrect assumptions about the signature of the extension method or the type of property, you can still do it with Delegate.CreateDelegate(), but take the comments about the PropertyInfo and the BindingFlags into account
You're trying to use list as the target of the delegate - but list is of type PropertyInfo, which sounds like it's not what you were expecting. Assuming you want to get the value of the property, and then call the method on that, you'll need to pass in the object containing the property as well, so you can get the actual list. (Alternatively, maybe it's "this" - you haven't really made that clear.) Either way, you can get the list itself and use that as the target. For example:
private Action<TListPropertyContainer, TDataValue>
CreateListPropertySetter<TListPropertyContainer, TDataValue>
(string listName, object target)
{
var listProperty = typeof(TListPropertyContainer).GetProperty(listName);
object list = listProperty.GetValue(target, null);
var method = typeof(Extensions).GetMethod("AddCSV");
return (Action<TListPropertyContainer, TDataValue>)Delegate.CreateDelegate(
typeof(Action<TListPropertyContainer, TDataValue>), list, method);
}
If this doesn't help, please edit your question with a short but complete console app demonstrating the problem. Right now there are too many unknowns to definitely help you.

C# Generics: How can I use them generically?

[TestMethod]
public void TestMyGenericBaseClasses()
{
Type typeCrazy = ThisPartyIsTypeCrazyWOOT();
// How do I create a generic object?
MadnessOhYeah<typeCrazy> sanity = new MadnessOhYeah<typeCrazy>();
// How do I use a generic object after it has been created?
Assert.IsTrue(sanity.MyTrueFunction(), "this is sparta");
// How do I call a generic function generically?
bool result = MyFunction<typeCrazy>();
Assert.IsTrue(result, "I did not get my teeth whitened!");
}
Is there any way to make this compile? (ThisPartyIsTypeCrazyWOOT returns a Type) Because this is a test, we're not concerned about having to use reflection or anything, unless that's just absolutely crazy.
I'm getting the vibe that this isn't going to be possible though, and that our test functions will just have to be more specific.
You need Type.MakeGenericType Method. Then Activator.CreateInstance Method.
Update 2: The first example I posted still doesn't 100% answer the question, since it involves a cast to List<int>, which is a type that is known at compile time. Below is a reflection-only solution that illustrates how you can use a generic type knowing nothing about the type argument itself. But, as you can see, it's... well, disgusting ;)
Type userType = GetUserSuppliedType();
// Now let's say userType is T.
// Then here we are getting the type typeof(List<T>).
// But, of course, there's no way to have any such information in the code.
Type listOfUserType = typeof(List<>).MakeGenericType(new[] { userType });
// This is effectively calling new List<T>();
object listObject = Activator.CreateInstance(listOfUserType);
// Do you see how messy this is getting?
MethodInfo addMethod = listOfUserType.GetMethod("Add");
// We better hope this matches userType!
object input = GetUserSuppliedInput();
// I suppose we could check it, to be sure...
if (input == null || input.GetType() != userType)
{
throw new InvalidOperationException("That isn't going to work!");
}
// Here we are finally calling List<T>.Add(input) -- just in the most ass-
// backwards way imaginable.
addMethod.Invoke(listObject, new[] { input });
Update: OK, if you insist on doing this, here's an example of how it's possible—but very cumbersome!
Type genericListType = typeof(List<>);
Type listOfInt32Type = genericListType.MakeGenericType(new[] { typeof(int) });
object listObject = Activator.CreateInstance(listOfInt32Type);
List<int> list = (List<int>)listObject;
list.Add(1);
Generics can't quite work like this because a Type object could be anything. Consider this code:
var list = new List<int>();
list.Add(1);
The type of list in the above code is known to be List<int>, which defines what operations are legal on list such as Add(1).
Now consider this instead:
Type t = GetTypeFromIndeterminateSourceSuchAsUserInput();
var list = new List<t>();
list.Add(?);
When t is a Type object rather than the name of a type (like int) which the compiler can parse, it's not really possible to instantiate a generic type using that type—or rather, it's possible (see Andrey's answer), but you can't really use the resulting object in any sort of generic way.
Now, you might think that something like this ought to work:
Type t = typeof(int);
var list = new List<t>();
list.Add(1);
...but just because the value of t is known (by you) at compile time doesn't change the way things work in general.
Anyway, yes it's possible using reflection; but if you go down that path, you're committing to a pretty reflection-heavy solution. What I'm getting at is that in general it isn't a particularly realistic thing to do.

Declare a generic type instance dynamically [duplicate]

This question already has answers here:
How do I use reflection to call a generic method?
(8 answers)
Closed 9 years ago.
Is it possible to declare an instance of a generic without knowing the type at design-time?
Example:
Int i = 1;
List<typeof(i)> list = new List<typeof(i)>();
where the type of i could be anything, instead of having to do:
List<int> list = new List<int();
If you don't know the type at compile-time, but you want the actual type (i.e. not List<object>) and you're not in a generic method/type with the appropriate type parameter, then you have to use reflection.
To make the reflection simpler, I've sometimes introduced a new generic type or method in my own code, so I can call that by reflection but then just use normal generics after that. For example:
object x = GetObjectFromSomewhere();
// I want to create a List<?> containing the existing
// object, but strongly typed to the "right" type depending
// on the type of the value of x
MethodInfo method = GetType().GetMethod("BuildListHelper");
method = method.MakeGenericMethod(new Type[] { x.GetType() });
object list = method.Invoke(this, new object[] { x });
// Later
public IList<T> BuildListHelper<T>(T item)
{
List<T> list = new List<T>();
list.Add(item);
return list;
}
Of course, you can't do an awful lot with the list afterwards if you don't know the type... that's why this kind of thing often falls down. Not always though - I've used something like the above on a few occasions, where the type system just doesn't quite let me express everything I need to statically.
EDIT: Note that although I'm calling Type.GetMethod in the code above, if you were going to execute it a lot you'd probably want to just call it once - after all, the method isn't going to change. You may be able to make it static (you could in the case above) and you probably want to make it private too. I left it as a public instance method for the simplicity of the GetMethod call in sample code - you'd need to specify the appropriate binding flags otherwise.
If you don't know the type at design-time, I'd say you have a list of OBJECTS (the base class for all other types).
List<object> list = new List<object>();
I think the best you are going to be able to do is something like this:
static void Main(string[] args)
{
int i = 1;
var thelist = CreateList(i);
}
public static List<T> CreateList<T>(T t)
{
return new List<T>();
}
You can also use Activator.CreateInstance. Example code snippet:
public class BaseRepository<T> where T : DataContext
{
protected T _dc;
public BaseRepository(string connectionString)
{
_dc = (T) Activator.CreateInstance(typeof(T), connectionString);
}
public void SubmitChanges()
{
_dc.SubmitChanges();
}
}
If you still want to type .Add(), .Remove(), do foreach etc. you can treat the List as a regular "old" System.Collections.IList,
since this interface is luckily implemented by List<T>.
And since all other posted answers to this question shows pretty much every other possible way to create an instance of a List<T> dynamically,
i will show one last way to do it.
I personally use this method when creating generic instances, when i don't really know nothing about the type at compile time,
and the type must be passed as a string, perhaps coming from the application configuration file.
In this example, T is System.String for simplicity but it could be anything:
Type T = typeof ( string ); // replace with actual T
string typeName = string.Format (
"System.Collections.Generic.List`1[[{0}]], mscorlib", T.AssemblyQualifiedName );
IList list = Activator.CreateInstance ( Type.GetType ( typeName ) )
as IList;
System.Diagnostics.Debug.Assert ( list != null ); //
list.Add ( "string 1" ); // new T
list.Add ( "string 2" ); // new T
foreach ( object item in list )
{
Console.WriteLine ( "item: {0}", item );
}

Categories

Resources