I need to find out if a Type I'm working with is a Generic 'container', for example if I have a List<int> I need to check if I'm working with a List (I know how to get whether I'm working with an int), how would I do that? (I'm thinking Reflection). Another example, I have a class called StructContainer<T>, I need to find the word (name) 'StructContainer', I'm not too bothered with what 'T' is, using reflection I get StructContainer'1, would hate to have to do some string splitting etc /EDIT: Just to explain further, StructContainer<int> I need 'StructContainer', Tuple<int> I need 'Tuple', List<int> I need 'List' and so forth
Your first question can be achieved in multiple ways:
Check whether your object implements IEnumerable<T>: yourObject is IEnumerable<int>. This only works if you know the type of the object in the container (int in this case)
Use the same solution I described below, just change StructContainer to List.
As to your second question, you can do this:
var yourObject = new StructContainer<int>();
var yourType = yourObject.GetType();
if(yourType.IsGenericType &&
yourType.GetGenericTypeDefinition() == typeof(StructContainer<>))
// ...
string type = yourObject.GetType().Name.Split('`')[0];
Related
I have a generic method
var propertyResolverMethod = _propertyResolver
.GetType()
.GetMethod(
nameof(_propertyResolver.GetEntities),
new[] { typeof(string), typeof(string) })
?.MakeGenericMethod(_itemType);
and the invocation
var recommendedItems = propertyResolverMethod
?.Invoke(
_propertyResolver,
new object[] { itemId, ResolvedCollectionId });
It on the compile-time it returns an object, but on runtime, it returns IQueryable<Item> this item is the item from _itemType and we find out its type only on runtime, but I know that it has a collection inside Item.RelatedItems that I need to get. Tried already casting to dynamic, but does not work for my case, I know that's somehow solvable via Expressions.
Should be iteratable like this
var itemIds = recommendedItems?.Select(i => i.RelatedItems.Select(s => s.ItemID));
But it's not possible without a proper cast
Hmm..
So if I get you correctly, you know this method returns an IQueryable<Item> where Item is the type previously stored in _itemType and you also know for a fact that this type always defines RelatedItems which in turn are an IEnumerable<T> or IQueryable<T> with Tdefining ItemID?
Is there a type that all possible _itemTypes inherit from that has RelatedItems defined? If so, you could try casting to that...
Else you could do more Reflection magic:
If you know that your result is an IQueryable<TItem>, you can extract the property-getter for RelatedItems with Reflection and pass that to the Select-function (which you can get by eithre casting to IQueryable<object> or by using ... again ... Reflection.
But to be honest that would be a very, very dirty way to do it and I would only do it as a last resort.
My first instinct right now would be to try refactoring the containing class (_itemType hints to me that this is a member field), so it is generic as well (inheriting from a non-generic class if you need that), so the class knows the type through its own type parameter.
Another solution would be to have a function like this:
private <Type of itemIDs> GetRelatedItemIds<TItem>(object source) {
return ((IQueriable<TItem>)source)?.Select(i => i.RelatedItems.Select(s => s.ItemID));
}
Now get that method via Reflection and use MakeGenericMethod(_itemType) on it, then invoke it with your result.
Just beware that your current selection will return a nested enumerable/queryable which each entry being a list of ItemIDs. If you didn't mean to do that, use SelectMany instead of the first Select which will automatically concatenate the inner enumerables/queryables.
I hope this helps you find a solution.
I am trying to get the actual object that is contained within a list that itself is contained within a task.
e.g. method has the following signature e.g.
public async Task<List<Dictionary<string,object>>> GetData()
i am currently using something like this:
var member = type.GetMembers()[0];
var returntype = member.ReturnType.GetGenericArguments();
var temp = member.ReturnType.GetGenericArguments()[0];
if (temp.GetGenericArguments().Count() > 0)
{
temp.GetTypeInfo().GetGenericArguments();
var innerttype = temp.GetGenericArguments()[0].FullName;
}
Currently the above code (which is not complete but just an extract from actual code) return system.object as fullname instead of Dictionary.
Any suggestions to solve this are welcome.
If you declare your dictionary to be of type <string, object> and and only ever insert objects inside it and not something higher up in the graph, you'll only ever get object typed objects out of it.
If you're storing all kinds of things in there and need to get their concrete type so you can interact with them, try to make them all conform to an interface first. Then, put the interface type in there replacing "object." If that doesn't work you can use generics. However, you'll still need to know the type ahead of time in order to be able to interact with it.
If you really have no idea what's in there and want to dig into it dynamically, that's precisely what Reflection was built for. You could also look into the dynamic type.
I'm trying to create objects dynamically but I don't know how to. What I need is, I have a class for that object, and objects properties are stored in the database. Then I'll need to compare the properties of each object to get the desired result.
So I need to dynamically create objects on the fly with the properties loaded from database.
I don't think you need to create objects dynamically, just create one statically that matches your db schema with the property details, then you can compare the values of the properties across rows, or within an instance of your object.
I have been working on something similar to this. There are several things:
Include the System.Reflection namespace
Create an object dynamically using Activator
Get the object properties using the myObjectType.GetProperties() method
Here is an example of a generic object creation function using the above methods:
using System.Reflection;
public static Item CreateItem<Item>(object[] constructorArgs, object[] propertyVals)
{
//Get the object type
Type t = typeof(Item);
//Create object instance
Item myItem = (Item)Activator.CreateInstance(t, constructorArgs);
//Get and fill the properties
PropertyInfo[] pInfoArr = t.GetProperties();
for (int i = 0; i < pInfoArr.Length; ++i)
pInfo.SetValue(myItem, propertyVals[i], null); //The last argument is for indexed properties
return myItem;
}
Of course the above example assumes that the values in the property value array are arranged correctly, which is not necessarily the case, but you get the idea.
With the PropertyInfo class you can get properties, get property names, get attributes associated with the properties, etc. Powerful technology. You should be able to do what you need with the above info, but if not let me know and I will add more info.
If you have a number of objects you want to instantiate from database values it can be done something like this.
//database code goes here, results go in results
List<ClassName> l = new List<ClassName>()
foreach(Row r in results){
l.Add(new ClassName(){ClassProperty1 = r.Property1,ClassProperty2 = r.Property2});
}
Are you talking about Dictionary?
var dict=new Dictionary<string, string>();
dict.Add("property1", "val1");
dict.Add("property2", "val2");
var prop2val=dict["property2"];
Maybe Activator is what your looking for?
http://msdn.microsoft.com/en-us/library/system.activator.aspx
Check this class, compile in the realtime. But it's performance is not quite good.
http://msdn.microsoft.com/zh-cn/library/microsoft.csharp.csharpcodeprovider(VS.80).aspx
You could use reflection to dynamically build your objects:
Reflection msdn reference
I think that you want to retrieve rows from the DB and directly assign them to object given that the properties of the object are equivalent to the columns of DB table. If that what you mean then I believe you can't :)
Rob Conery did a small project called Massive that pretty much does what you're trying to accomplish. It's essentially a small ORM, in 400 lines of Dynamic C# 4.0 code.
Rob has been doing this kind of thing for quite some time with SubSonic, so you might find his approach with Massive quite interesting.
http://blog.wekeroad.com/helpy-stuff/and-i-shall-call-it-massive
Some of the code is explained here, with examples:
http://blog.wekeroad.com/microsoft/the-super-dynamic-massive-freakshow
Is it possible to overload how a type resolves properties when cast to dynamic?
Basically what I am trying to do is something like ExpandoObject where you can access new properties on the fly, but instead of those properties being whatever gets assigned to them, I want them all to be collections of strings, and when you access one, it calls a dictionary web service which returns all of the definitions of the word. I want it to be dynamic so that you can specify any word at all.
I'm thinking the usage would be something like this:
dynamic dictionary = new DictionaryWebservice();
var awesome = dictionary.awesome;
foreach(var definition in awesome)
{
// add definition to my output
}
Is this possible?
Yes, derive your type from System.Dynamic.DynamicObject.
Remember though that everything you return from a dynamic method is itself dynamic. Therefore, even the var definition in your foreach will be of type dynamic.
I'm writing a custom deserializer that will deserialize a list by deserializing each of the individual objects in the collection and then putting it together.
Basically my code looks like this:
//myField is a FieldInfo that represents the field we want to put the data in
//resultObject is the object we want the data to go into
List<Object> new_objects = new List<Object>();
foreach (String file_name in file_name_list)
{
Object field_object = MyDeserialization(file_name)
new_objects.Add(field_object)
}
myField.SetValue(resultObject, new_objects);
But this gives an error on the SetValue because (for example) I am trying to put a List(Object) into a List(Int32). Note that this problem only occurs with collections. The following code:
Object new_object = MyDeserialization(file_name)
myField.SetValue(resultObject, new_object)
works just fine provided that the runtime type of the result of MyDeserialization(file_name) is actually compatible with the type of myField. What is the problem here, and is there a way to make the collection deserialization work? (I've tried replacing the List(Object) declaration with myField.FieldType and that won't even compile.
Collections do not offer covariance... a List<int> simply isn't a List<object> (or v.v.). As such, you need to identify the T, for example like so (using the FieldInfo.FieldType) - and create the right type of list in the first place.
For convenience, once created it may be simpler to use the non-generic IList interface:
Type listType = typeof(List<>).MakeGenericType(itemType);
IList list = (IList)Activator.CreateInstance(listType);
list.Add(...); // etc
However; I must stress - writing a full (and robust) serializer is a lot of work. Do you have a specific reason? Many of the inbuilt serializers are pretty good - for example DataContractSerializer - or 3rd party, such as Json.Net, and (if I do say so myself) protobuf-net.
The problem is that .NET can't know that your List is actually a List. The following code should work:
//myField is a FieldInfo that represents the field we want to put the data in
//resultObject is the object we want the data to go into
List<MyType> new_objects = new List<MyType>();
foreach (String file_name in file_name_list)
{
Object field_object = MyDeserialization(file_name)
new_objects.Add((MyType)field_object)
}
myField.SetValue(resultObject, new_objects);
For Fun Linq Extra Credit (assuming file_name_list is IEnumerable):
myField.SetValue(resultObject, file_name_list
.Select(s => MyDeserialization(s))
.Cast<MyType>()
.ToList());