See i have a situation like this...
object myRoledata = List<Roles>() --> (some list or Ienumerable type)
Now i have a generic method which creates an XML object from List<T> -
Something like this..
public string GetXML<T>(object listdata)
{
List<T> objLists = (List<T>)Convert.ChangeType(listData, typeof(List<T>));
foreach(var obj in listdata)
{
//logic to create xml
}
}
Now in order to run this method I have to do like this:
string xml = GetXML<Roles>(myRoledata);
Now i dont know what Type may come to me to be passed to GetXML method. I have a method which will call GetXML for different Types e.g. Roles, Users etc
now i can get the Type within the List<> like this
Type genericType = obj.GetType().GetGenericArguments()[0];
but cannot pass it like this
string xml = GetXML<genericType>(myRoledata);
Is there anyway in which i can pass any genericTypes to GetXML method?
To do that, you need to use reflection;
typeof(SomeClass).GetMethod("GetXML").MakeGenericMethod(genericType)
.Invoke(inst, new object[] {myRoleData});
where inst is null if it is a static method, this for the current instance (in which case you can also use GetType() instead of typeof(SomeClass)), or the target object otherwise.
Since you cast your listdata parameter as a List< T> in the first line of your method, why don't you just change the method signature to
public string GetXML<T>(List<T> listdata)
That way, you don't have to use reflection to get the generic arguments.
EDIT: I see that you need to be able to accept IEnumerable collections, and not just lists. So, consider changing your method signature to
public string GetXML<T>(IEnumerable<T> listdata)
This is a problem you probably want to avoid solving. It is possible, via reflection, to call methods dynamically without statically resolving them - but it kind of defeats the whole point of the type-annotations.
Either do this:
public string GetXML(IEnumerable listdata) {
foreach(object obj in listdata)
//logic to create xml
}
... which you now can call with any IEnumerable, or write it the "modern" way as:
public string GetXML(IEnumerable<object> listdata) {
foreach(object obj in listdata)
//logic to create xml
}
... which you can call with any IEnumerable via GetXML(someEnumerable.Cast<object>()) and in C# 4.0 even directly by covariance.
If you need the type of an element runtime, you can get it using .GetType() on each element, or you can just pass it in as a parameter (and provide an override for backwards-compatibility):
public string GetXML(Type elementType, IEnumerable<object> listdata) {
foreach(object obj in listdata)
//logic to create xml
}
public string GetXML<T>(IEnumerable<T> listdata) {
return GetXML(typeof(T),listdata.Cast<object>());
}
Incidentally, if you're constructing XML, a string is probably a less robust return-type choice: if possible, you could work with something like an XElement instead - and get xml-validity guarantee's to boot.
I don't know your situation, but is it possible to rewrite your function as:
public string GetXML<T>(IEnumerable<T> listdata)
{
foreach(var obj in listdata)
{
//logic to create xml
}
}
Then it can be called as:
List<Role> myList;
GetXML(myList);
You can add type parameters as far back as needed to support it, till you get to somewhere that does know what the solid type is.
You have the right idea, but you are using the wrong method. Have a look at Type.MakeGenericType or MethodInfo.MakeGenericMethod. It will take a few more lines than your example, but it should be simple to solve.
GetGenericArguments() can be used to get the Roles type from a List. It's the differnt way around.
Btw: Looks like your implementing some kind of XML serialization. Make sure you check existing classes, before reinventing the wheel. ;-)
Related
I am trying to get two different return values from dictionary extension methods for convenience. The first being an Item of the RealType, the other being a List<RealType>.
The problem / question is this: Getting a single RealType item works like a charm, getting the List crashes and calls for IConvertable implementation. Is there no build in call to convert a full list?
Edit: I am trying to convert from Base Class to Derived Class, not the other way around. Also, I 100% know the data will be of type Derived Class and the caller is passing the correct type each time, without any chance of error.
Why is that? Can I avoid it, without "dirty" tricks?
There are about two dozen RealType - classes that all extend from MyAbstractModel and get saved in a
List<Dictionary<string, MyAbstractModel>. Writing code for two dozen conversions seems like no good idea, when a small dirty (?) trick seems to do it as well.
Consider the following (working) DictionaryExtention class
public static class DictionaryExtenders
{
public static T GetItem<T>(this Dictionary<string, MyAbstractModel> instance, string key)
{
return (T)Convert.ChangeType(instance[key], typeof(T));
}
}
Called like this: RealType item = myDictionary.GetItem<RealType>("choosenIDString");
Edit: Each Dictionary can and will only ever have one type present. There won't ever be two different types stored in one. Yes, this code would allow that and spew out errors, but a saveguard is not needed in this case and is not part of my question.
Now in contrast, the following GetList<RealType> extention calls for IConvertable implementation:
public static List<T> GetList<T>(this Dictionary<string, MyAbstractModel> instance)
{
return (List<T>)Convert.ChangeType(instance.Values.ToList(), typeof(List<T>));
}
I feel like I am missing something here, because the following workaround also returns a List<RealType>, but does not call for IConvertable. I simply loop the dictionary and call GetItem<T>()each time.
public static List<T> GetList<T>(this Dictionary<string, MyAbstractModel> instance)
{
var temp = new List<T>();
foreach (RealType myType in instance.Values.ToList())
{
temp.Add(instance.GetItem<T>(myType.ID));
}
return temp;
}
This does not feel like a solid solution, but like a workaround. What am I missing here? Do the Lists give me a hard time due to faulty syntax on my side, or is there a reason I have to understand?
Your GetList implementations are not valid. All values in dictionary are instances of classes derived from MyAbstractModel but you can't cast them each other in all cases. For example, ModelA and ModelB are both derived from MyAbstractModel. But you can't cast ModelA to ModelB. You can write something like this:
public static List<T> GetList<T>(this Dictionary<string, MyAbstractModel> instance) where T: MyAbstractModel
{
return instance.Values.OfType<T>().ToList();
}
In that case you'll receive all values of particular type T.
you can try this way
public static List<T> GetList<T>(this Dictionary<string, yourModel> instance)
{
return instance.Values.Select(d => (T)Convert.ChangeType(d, typeof(T))).ToList();
}
I have object XML serialized messages coming into a class called MessageRouter. The XML contains the Type name it it was serialized from, and I need to be able to invoke different delegate methods depending on the type that are not known until runtime. I'm not extremely strong in generics so hopefully this will make sense to someone...
I'd like MessageRouter to provide a RegisterDelegateForType method like so:
myMessageRouter.RegisterDelegateForType(new Action<MySerializableType>(myActionHandler));
And then store the types, or the type's string representation in a Dictionary like this:
Dictionary<Type, Action<T>> registeredDelegates;
That way, I can do something like the following pseudocode, calling the type's assigned delegate and passing the deserialized object:
Type xmlSerializedType = TypeFromXmlString(incomingXml);
object deserializedObject = DeserializeObjectFromXml(xmlSerializedType, incomingXml);
// then invoke the action and pass in the deserialized object
registeredDelegates[xmlSerializedType](deserializedObject);
So my questions are:
How do you define a Dictionary that can contain a Type as a key and a generic Action<T> as a value, and have the RegisterDelegateForType method populate the dictionary?
If that's not possible, what's the best way to do this?
You cannot do this as described, for quite obvious reasons - even if somehow allowed, the last line of code in your example (the one which retrieves a delegate and then calls it) would be non-typesafe, as you're calling an Action<T> - which expects T as an argument - and yet passing it deserializedObject, which is of type object. It wouldn't work in plain code without a cast, why would you expect to be able to circumvent the type check for your case?
In the simplest case, you can do something like this:
Dictionary<Type, Delegate> registeredDelegates;
...
registeredDelegates[xmlSerializedType].DynamicInvoke(deserializedObject);
Of course this will allow someone to add a delegate which takes more or less than one argument to the dictionary, and you'll only find out at DynamicInvoke call, at run-time. But there isn't really any way to define a type which says "any delegate, but with 1 argument only". A better option might be this:
Dictionary<Type, Action<object>> registeredDelegates
and then registering types like this:
myMessageRouter.RegisterDelegateForType<MySerializableType>(
o => myActionHandler((MySerializableType)o)
);
The above snippet uses C# 3.0 lambdas, but you can do the same - if slightly more verbose - with C# 2.0 anonymous delegates. Now you don't need to use DynamicInvoke - the lambda itself will do the proper cast.
Finally, you can encapsulate the lambda creation into RegisterDelegateForType itself by making it generic. For example:
private Dictionary<Type, Action<object>> registeredDelegates;
void RegisterDelegateForType<T>(Action<T> d)
{
registeredDelegates.Add(typeof(T), o => d((T)o));
}
And now the callers can just do:
RegisterDelegateForType<MySerializableType>(myHandler)
So it's completely typesafe for your clients. Of course, you're still responsible for doing it right (i.e. passing an object of the correct type to the delegate you retrieve from the dictionary).
I am not sure that this completely answers your question, but here is a class I wrote that will accomplish what you want. I couldn't tell if you want your Action delegate to take a typed object or not, but in your pseudo code, you pass it an "object" to deserialize so I wrote my class accordingly and it therefore does not use generics:
public delegate void Action(object o);
public class DelegateDictionary {
private IDictionary _dictionary = new Hashtable();
public void Register<T>(Action action) {
_dictionary[typeof(T)] = action;
}
public Action Get<T>() {
return (Action)_dictionary[typeof(T)];
}
public static void MyFunc(object o) {
Console.WriteLine(o.ToString());
}
public static void Run() {
var dictionary = new DelegateDictionary();
dictionary.Register<string>(MyFunc);
// Can be converted to an indexer so that you can use []'s
var stringDelegate = dictionary.Get<string>();
stringDelegate("Hello World");
}
}
I believe this will accomplish what you want.
I have a generic interface called IValueBridge which serves as a generic bridge to get the values from any arbitrary object by providing the properties name (also nested properties are possible, e.g. myFoo.MyProp.Name):
public interface IValueBridge<in T> : IValueBridge
{
object GetValue(T instance, string attributeName);
}
Now there is an implementing class:
public class ValueBridge<T> : IValueBridge<T>
{
public object GetValue(T instance, string attributeName)
{
Func<T, object> f = // ...
return f(instance);
}
}
Now with this setting I wanto to use that bridge in order to get the values for any arbitrary object without knowing its type at compile-type.
What I WANT to achieve is something similar to this:
object bar = ...;
var bridge = new ValueBridge<typeof(bar>();
I know how to create instances of generic types via reflection using MakeTypeGeneric. However what Activator.CreateInstance returns is an object and I cannot cast it to the actual type Bar (which I don´t know at compile-time) and thus cannot access GetValue<T> on it.
Is there a way I can access GetValue<T> without any more reflection? I´d like to avoid more reflection as the method is called very often and calling it via reflection is considered quite slow. That´s why I cache the Func<T, object> to be called inside.
I found a quite nice solution using a wrapper-interface which IValueBridge<T> extends:
public interface IValueBridge
{
object GetValue(object instance, string attributeName);
}
Now my actual ValueBridge looks like this:
public class ValueBridge<T> : IValueBridge<T>
{
object IValueBridge.GetValue(object instance, string attributeName)
{
return this.GetValue((T)instance, attributeName);
}
public object GetValue(T instance, string attributeName)
{
Func<T, object> f = // ...
return f(instance);
}
Now you can use ((IValueBridge) myBridge).GetValue(...) . As the parameter can be cast to its actual type within the ValueBridge ((T) instance)) we can now invoke the generic version of the method directly without any reflection.
Note that you have to explicitely implement any of the two interfaces to avoid confusion which method to call from within the wrapper.
The reason I self-answer that question is that I got much head-ache on solving it and want to share the result of my thoughts to the community.
I'm having trouble converting a list object back to its original type without an explicit cast. My intention is to generalize methods so I could pass in different db Types such as Person or Company. I have no problem getting the values via reflection but I need to convert the actual list back to its original type List<typeT> instead of List<object> in the method I am passing it to. I am aware of the following methods:
SomeList.ConvertAll(x => (typeT)x);
SomeList.Cast<typeT>().ToList();
However for these methods I will have to explicitly cast typeT. I have tried the following:
formatted1.ConvertAll(x => Convert.ChangeType(x, typeT));
and
List<dynamic> newList = new List<dynamic>();
foreach (var p in SomeList)
{
newList.Add(Convert.ChangeType(p, typeT);
}
No success thus far. Maybe I should have another game-plan for generalizing these methods altogether. right now I'm passing the lists in as follows:
public string returnJson(List<object> entity, string someString)
{
}
It seems like making returnJson generic would resolve most of these problems:
public string returnJson<T>(List<T> entity, string someString)
{
}
Now returnJson can be used generically, like:
returnJson<Company>(listOfCompanies, "someString");
and
returnJson<Person>(listOfPersons, "someOtherString");
You can still reflect over the objects, but the list is always a list of the type that you need at compile time. No casting required.
Why not use generics, that way the calling function can do what it needs:
public string returnJson<T>(List<T> entity, string someString)
{
//not sure what someString is for or why you need the type for this naming scheme
JavaScriptSerializer jss = new JavaScriptSerializer();
return jss.Serialize(entity);
}
You can use the dynamic keyword and reflection to create the list.
dynamic newList = Activator.CreateInstance(typeof(List<>).MakeGenericType(typeT));
foreach (var p in SomeList)
{
newList.Add(p);
}
CallOtherMethodOverloadedForListOfPersonCompanyEtc(newList)
public static List<T> GetColumnValuesByHeader<T>(string docName)
{
// How can i get T as Customer or Employee in here?
}
List<Customer> customers = GetColumnValuesByHeader<Customer>("Customers.dat")
List<Employee> employees= GetColumnValuesByHeader<Employee>("Employees.dat")
Use typeof(T):
public static List<T> GetColumnValuesByHeader<T>(string docName)
{
// Will print Customer or Employee appropriately
Console.WriteLine(typeof(T));
}
Now what exactly you do with that afterwards is up to you...
If you actually need to handle the cases differently, then I'd be tempted to write separate methods to start with. Generics are really designed for algorithms which behave the same way for any type. There are exceptions to every rule, of course - such as optimizations in Enumerable.Count<T>... and if you're fetching properties by reflection, for example, then that's a reasonable use of typeof(T).
As Jon Skeet said you can use typeof to get the type of T. You can also use the Activator class to create an instance of that class.
Type theType = typeof(T);
object obj = Activator.CreateInstance(theType);
Assuming you want to create many T to populate your list, the simplest way is to use Activator.CreateInstance<T>();. You wanna add the where T : new() constraint to your method though, to make this easy. It'll assume Customer and Employee each have a default constructor - if that isn't the case, you can still use CreateInstance(), but you'll need to grab the correct arguments to pass by getting the ConstructorInfo for each type.
You can get the type of T using typeof..
Type t = typeof(T);
if (t == typeof(Employee))
{
//Do something here ...
}
if (type of T Is Customer) {
//Perform action for customer
} else
if (type of T Is Employee) {
//Perform action for Employee
}