Dynamic typing in C# - c#

I know this does not work, however does anyone have a way of making it work?
object obj = new object();
MyType typObj = new MyType();
obj = typObj;
Type objType = typObj.GetType();
List<objType> list = new List<objType>();
list.add((objType) obj);
EDIT:
Here is the current code: http://github.com/vimae/Nisme/blob/4aa18943214a7fd4ec6585384d167b10f0f81029/Lala.API/XmlParser.cs
The method I'm attempting to streamline is SingleNodeCollection
As you can see, it currently uses so hacked together reflection methods.

It seems you're missing an obvious solution:
object obj = new object();
MyType typObj = new MyType();
obj = typObj;
List<MyType> list = new List<MyType>();
list.Add((MyType) obj);
If you really need the dynamic route, then you could do something like this:
object obj = new object();
MyType typObj = new MyType();
obj = typObj;
Type objType = typObj.GetType();
Type listType = typeof(List<>);
Type creatableList = listType.MakeGenericType(objType);
object list = Activator.CreateInstance(creatableList);
MethodInfo mi = creatableList.GetMethod("Add");
mi.Invoke(list, new object[] {obj});

You need reflection:
constructor = typeof (MyType).GetConstructor () // doing this from memory, the typeof might be wrong, I'm sure someone will edit it
typObj = (MyType) constructor.Invoke ()
It can also be done for generics but that is a bit trickier.

You can do something like this using Generics, I'm not really sure what the point of it would be though.
public List<T> TypedList<T>() where T : new()
{
object obj = new object();
T typObj = new T();
obj = typObj;
List<T> list = new List<T>();
list.Add((T)obj);
return list;
}

object obj = new object();
Type objType = obj.GetType();
IList list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(objType));
list.Add(obj);
With this you will get an runtime error if you try to put something into list that is not assignable from objType.

Even though it seems answered, I still don't get it :)
Wouldn't it be useful to have the "typeToReturn" as generic argument to the function?
public List<T> SingleNodeCollection<T>(String xPath, XPathNavigator navigator)
where T : new()
{
XPathNodeIterator nodes = navigator.Select(xPath);
List<T> returnedList = new List<T>(nodes.Count);
...
T newObj = new T();
...
Type t = typeof(T); // need the type anyway?
}

public class myClass
{
}
myClass instance = new myClass();
Type t = instance.GetType;
//top is just to show obtaining a type...
public object GetListOfType(Type t)
{
Type listType = typeof(List<>);
var listOfType = listType.MakeGenericType(t);
var listOfMyClassInstance = Activator.CreateInstance(listOfType);
return listOfMyClassInstance;
}
but eventually you have to cast... using your type directly
List<object> listOfMyClass = GetListOfType(t);
listOfMyClass.Add(myClassInstance);
((myClass)listOfMyClass[0]).SomeProperty

Faster would be to use Reflection.Emit
Here's a simple example of using Reflection.Emit for instantiating an arbitrary concrete type at runtime. For your purposes, you just need to have it call the ctor of List instead of T.ctor as in the example.

I'm not entirely sure what you are trying to do, but would this work:
var obj = new MyType();
I might be misunderstanding your question though.
(I edited this to fix sample code which wouldn't compile, thanks for the comment)

Related

Make a castable type from GetType?

Explained below in the code snippet, I can't figure out the syntax for this:
object tcsObject = new TaskCompletionSource<Apple>();
Apple apple = new Apple();
// How do I do this?
TaskCompletionSource<apple.GetType>() tsc = tscObject as TaskCompletionSource<apple.GetType>()
edit
Should note the particular issue I am trying to figure is how to do this generics cast without initially knowing that the the type is Apple. The type could end up being anything, so I am looking to do this operation from what is returned via GetType.
If you don't mind sacrificing compile-time type safety, you could make use of Convert.ChangeType() and the dynamic keyword like so:
static dynamic ConvertTo(this object source, Type targetType)
{
return (dynamic)Convert.ChangeType(source, targetType)
}
public void YourActualCode()
{
object tcsObject = new TaskCompletionSource<Apple>();
Apple apple = new Apple();
TaskCompletionSource<Apple> tsc = ConvertTo(tscObject, typeof(TaskCompletionSource<Apple>))
}
The nice thing about this approach is you can defer determination of the parameter type until runtime:
var wrapperType = typeof(TaskCompletionSource<>);
var paramType = typeof(Apple);
var concreteType = wrapperType.MakeGenericType(paramType);
TaskCompletionSource<Apple> tsc = ConvertTo(tscObject, concreteType);

Instantiate Generic Type from type [duplicate]

Is it possible to achieve the following code? I know it doesn't work, but I'm wondering if there is a workaround?
Type k = typeof(double);
List<k> lst = new List<k>();
Yes, there is:
var genericListType = typeof(List<>);
var specificListType = genericListType.MakeGenericType(typeof(double));
var list = Activator.CreateInstance(specificListType);
A cleaner way might be to use a generic method. Do something like this:
static void AddType<T>()
where T : DataObject
{
Indexes.Add(typeof(T), new Dictionary<int, T>());
}

Reflection Get List<> from List<T> (Container type from generic container type)

I have a peculiar situation where in one of reflectors I can get different types of containers that I need to reinflate (like make clones of). This started happening when new type of container was introduced (ObservableCollection<T>)
Within cloning mechanism what I have found was this:
if (property.PropertyType.FullName.Contains(ReflectorResources.ListName) || property.PropertyType.FullName.Contains("ConcurrentBag"))
{
var listElementType = property.PropertyType.GenericTypeArguments[0];
var newList = (property.PropertyType.FullName.Contains(ReflectorResources.IncidentListName))
? Activator.CreateInstance(typeof(Definitions.Session.Products.Motor.IncidentList<>).MakeGenericType(listElementType))
: property.PropertyType.FullName.Contains("ConcurrentBag") ? Activator.CreateInstance(typeof(ConcurrentBag<>).MakeGenericType(listElementType)) : Activator.CreateInstance(typeof(List<>).MakeGenericType(listElementType));
var oneItem = Activator.CreateInstance(listElementType);
}
So I tried to rewrite it like:
if (new[] { ".Collections." }.Any(o => property.PropertyType.FullName.Contains(o)))
{
var listElementType = property.PropertyType.GenericTypeArguments[0];
var listType = property.PropertyType;
var constructedListType = listType.MakeGenericType(listElementType);
var newList = Activator.CreateInstance(constructedListType);
var oneItem = Activator.CreateInstance(listElementType);
}
however it blows up on the line: var constructedListType = listType.MakeGenericType(listElementType); with error
System.InvalidOperationException : Method may only be called on a Type for which Type.IsGenericParameter is true.
My guess is that I need to extract List<> type from List<Something>...
How do I get container type from generic container type?
Instead of this:
var listElementType = property.PropertyType.GenericTypeArguments[0];
var listType = property.PropertyType;
var constructedListType = listType.MakeGenericType(listElementType);
Try this:
Type listElementType = property.PropertyType.GenericTypeArguments[0];
Type constructedListType;
if (! property.PropertyType.IsGenericTypeDefinition)
constructedListType = property.PropertyType;
else
{
// Depending on where your property comes from
// This should not work in the case the property type is List<T>
// How listElementType should allow you to instantiate your type ?
var listType = property.PropertyType.GetGenericTypeDefinition();
constructedListType = listType.MakeGenericType(listElementType);
}
I was also saying you should look at GetGenericTypeDefinition() method, but there was already the AakashM's answer before I finished to write this.
Then you should take a look at his answer.
I am going to quote from this answer, which probably answers any question you have about reflection and generics:
To get the unbound type from a constructed type at runtime, you can
use the Type.GetGenericTypeDefinition method.
Type listOfInt = typeof(List<int>);
Type list = listOfInt.GetGenericTypeDefinition(); // == typeof(List<>)

How to create specific list type whose parameter is known at runtime and then loop through this list?

I know I can create an object whose type is known only at run time like this:
Type t = record.GetType();
var src = Activator.CreateInstance(t.BaseType);
How can I do something like List<Record>=new List<Record>() at run time?
Suppose I am getting Child Record list using Reflection like this
var ChildRecorList=src.GetType().GetProperty(propName).GetValue(src, null);
and how can then I loop through this using foreach or for loop because foreach only works for known type list. It does now work with var types. Is there way to cast Reflection value to cast at specific type whose value is known at runtime(mentioned in point 1)
You can try this to create generic type in runtime:
Type genericListType = typeof (List<>);
// if you have more than one generic argumens
// you can add your types here like typeof(MyClass),typeof(MyClass2)
Type[] genericArguments = { typeof (Record) };
// create your generic type with generic arguments
Type myGenericType = genericListType.MakeGenericType(genericArguments);
// and then you can create your instance
var recordList = Activator.CreateInstance(myGenericType);
// get your property value
recordList = src.GetType().GetProperty(propName).GetValue(src, null);
And I guess you sure your type is a List then when you creating your instance you can make a cast like this:
var recordList = (IList)Activator.CreateInstance(myGenericType);
Then you can loop through your list
foreach (var item in recordList)
{
...
}
I'm not sure If you're looking for something like this, But you can use List Inside another List or Dictionary, Also, You can store the base value with any type and get the type whenever needed, I recommend using Dictionary so that way you can name your lists:
Dictionary<String, List<Object>> Data = new Dictionary<String, List<Object>>();
Data["MyUser"] = new List<Object>();
Data["MyUser"].Add(MyDBObject);
var obj = Data["MyUser"].Find(x => x.MyKey == "MyKeyObject");
var t = obj.GetType();
var dta = (MyDBObject)obj;
foreach (var db in Data)
{
if (db.Key == "MyUser")
db.Value.Find(x => x.Name == "MyName");
}
Or If you're looking for Creating lists on runtime:
List<List<Object>> Data = new List<List<Object>>();
var mydb = Data.Count;
Data.Add(new List<Object>());
Data[mydb].Add(MyOBJ);
foreach (var db in Data)
{
if (db.Contains(MyOBJ)
return db;
}
Why don't you just use generics? You could do something like this:
public void DoSomething<T>(T type)
{
var list = new List<T>();
}
This will allow you to create a list from whichever type is passed in at runtime.

How to retrieve Object from arraylist in c#

How to retrieve Object and its member from arraylist in c#.
You mean like this?
ArrayList list = new ArrayList();
YourObject myObject = new YourObject();
list.Add(myObject);
YourObject obj = (YourObject)list[0];
To loop through:
foreach(object o in list)
{
YourObject myObject = (YourObject)o;
.......
}
Information on ArrayList
object[] anArray = arrayListObject.ToArray();
for(int i = 0; i < anArray.Length; i++)
Console.WriteLine(((MyType)anArray[i]).PropertyName); // cast type MyType onto object instance, then retrieve attribute
Here's an example of a simple ArrayList being populated with a new KeyValuePair object. I then pull the object back out of the ArrayList, cast it back to its original type and access it property.
var testObject = new KeyValuePair<string, string>("test", "property");
var list = new ArrayList();
list.Add(testObject);
var fetch = (KeyValuePair<string, string>)list[0];
var endValue = fetch.Value;
You should use generic collections for this. Use the generic ArrayList so you dont have to cast the object when you are trying to get it out of the array.
You can also use extension methods:
ArrayList list = new ArrayList();
// If all objects in the list are of the same type
IEnumerable<MyObject> myenumerator = list.Cast<MyObject>();
// Only get objects of a certain type, ignoring others
IEnumerable<MyObject> myenumerator = list.OfType<MyObject>();
Or if you're not using a newer version of .Net, check the object type and cast using is/as
list[0] is MyObject; // returns true if it's an MyObject
list[0] as MyObject; // returns the MyObject if it's a MyObject, or null if it's something else
Edit: But if you're using a newer version of .Net...
I strongly suggest you use the Generic collections in System.Collections.Generic
var list = new List<MyObject>(); // The list is constructed to work on types of MyObject
MyObject obj = list[0];
list.Add(new AnotherObject()); // Compilation fail; AnotherObject is not MyObject
Do a type casting like this:
yourObject = new object[]{"something",123,1.2};
((System.Collections.ArrayList)yourObject)[0];

Categories