convert class string to class - c#

I have the code below in my ASP.NET app, I would like to convert converterName variable to
Class and pass it to FillRequest<T> method.
Is it possible?
var converterName = HttpContext.Current.Items["ConverterName"] as string;
FillRequest<Web2ImageEntity>(Request.Params);
Alternatively I could do
var converterName = HttpContext.Current.Items["ConverterName"] as string;
if (converterName == "Web2ImageEntity")
FillRequest<Web2ImageEntity>(Request.Params);
but I have about 20 entity classes and I would like to find a way to write code as short as possible.

That would not be possible as the generic type needs to be specified at the compile time.
What you can do is change the FillRequest method to be something like below and then use reflection to do the desired task
FillRequest(string[] params,Type converter)
{
//Create object from converter type and call the req method
}
Or make the FillRequest take a Interface
FillRequest(string[] params, IConverter c)
{
//call c methods to convert
}
Calling this would be something like:
var type = Type.GetType(converterName);
FillRequest(Request.Params,(IConverter)Activator.CreateInstance(type));

Yes, take a look at Activator.CreateInstance():
var converterName = HttpContext.Current.Items["ConverterName"] as string;
var type = Type.GetType(converterName);
var yourObject = Activator.CreateInstance(type);
Be aware that the type must have a public parameterless constructor. Here is a link to the MSDN documentation; there are a bunch of overloads which might be useful to you:
http://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx
UPDATE: If you must pass the object to a method with a generic type, then you will run into problems because the type is not known at compile time. In that case, I would consider having all of your converters implement a common interface, something like this:
var converterName = HttpContext.Current.Items["ConverterName"] as string;
var type = Type.GetType(converterName);
var yourObject = Activator.CreateInstance(type) as IMyConverter;
if (yourObject != null)
FillRequest<IMyConverter>(yourObject);

I found code idea here. Peter Moris pointed that he took code from Jon Skeets book, so if it will be useful - high five to Jon :)
create method:
public void DoFillRequest(Type type, string[] params)
{
MethodInfo methodInfo = this.GetType().GetMethod("FillRequest");
MethodInfo genericMethodInfo = methodInfo.MakeGenericMethod(new Type[]{ type });
genericMethodInfo.Invoke(this, new object[]{ params });
}
and now call it:
var type = Type.GetType(converterName);
DoFillRequest(type, Request.Params);

Related

How to set Generic Type T as string in C#

I Have the full name of a type as string and I would like to use this string to tell type of a generic method. see this
string typeStr ="Dll.NameSpace.MyType";
var list = new List<Dll.NameSpace.MyType>();//should put typeStr here
var result = call.SomeGenericMethod<...>(obj);//should put typeStr here
This answer didn't help me. If you try visiting this other one, it does not satisfy my needs.
EDITS: The generic method I'm trying to call is an extension one. I have unsuccessfully tried the following code,
method remains null
var result = repo.Get();
Type elementType =
Type.GetType("x2o_Care.Models.ViewModels.PatientViewModel");
MethodInfo method =typeof(AutoMapper.QueryableExtensions.Extensions)
.GetMethod("ProjectTo", new[] { typeof(IQueryable)});
MethodInfo generic = method.MakeGenericMethod(elementType);
var model = generic.Invoke(result.OrderBy(e => true).Take(20), null);
Your code is exactly what you need. You just need to specify exactly what overload of ProjectTo method you need as there are a few. Make sure to specify all the parameters in GetMethod/
For example:
MethodInfo method =typeof(AutoMapper.QueryableExtensions.Extensions)
.GetMethod("ProjectTo", new[] { typeof(IQueryable),
typeof(object),
typeof(Expression<Func<TDestination, object>>[])
});
Here is a list of all the ProjectTo methods:
https://github.com/AutoMapper/AutoMapper/blob/master/src/AutoMapper/QueryableExtensions/Extensions.cs

How to check method exists in C# with certain particular signature?

I want to check if the method for certain parameters is implemented. In this scenario, I have for example these method overloads:
public class Transformations
{
public string TransformFrom(string s) { return s;}
public string TransformFrom(int i) { return "00" + i.ToString();}
public string TransformFrom(DateTime dt) { return
DateTime.ToString("MM/dd/yyyy HH:mm:ss.fff");}
}
Suppose I have decimal like:
object obj = 1M;
If I now call TransformFrom(obj), I get an exception.
Other part of my program returns unfortunately only objects, which really are concrete types like int or datetime. And I want to transform some of these objects to string so that those can be written to the log. So this is a runtime problem. Also I want that my Transformations-class is general enough to be used in other programs too, so there can be objects of any type.
Is there fast way to find out that this method overload does not exist?
Either way you are currently going to get a compile time error, even if there was an overload that accepted a decimal. You can approach this one of 2 ways depending on your needs:
To resolve this at compile time you have to cast to the correct type.
object obj = 1;
var objAsInt = (int) obj;
var result = transformationInstance.TransformFrom(objAsInt);
If there is no proper overload you will get a compile time error and you can resolve this at design time.
To resolve this at runtime use reflection to figure out if there is an overload of the type and if there is pass the instance.
object obj = 1;
var underlyingType = obj.GetType();
var method = typeof(Transformations).GetMethod("TransformFrom", new Type[] { underlyingType });
if(method != null)
{
var result = method.Invoke(transformationInstance, new []{obj});
}
It is possible to find out whether a given overload exists using reflection:
public static bool HasOverloadForArgument(Type targetType, string methodName, object arg)
{
var methodInfo = targetType.GetMethod(name: methodName, types: new[] { arg.GetType() });
return methodInfo != null;
}
Live sample
I'm not sure what is the whole idea here as there won't be much you can do when the transformation is not available during runtime.
Maybe, you'd just be best off using dynamic to avoid all the reflection stuff and caching required otherwise, e.g.
var boxedInt = (object)1;
var boxedFloat = (object)1f;
dynamic dynamicInt = boxedInt;
dynamic dynamicFloat = boxedFloat;
var intResult = new Transformations().TransformFrom(dynamicInt); // works
var floatResult = new Transformations().TransformFrom(dynamicFloat); // throws binder exception

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.

How can I pass a type, rather than an instance, to a function in C#?

I am attempting to use reflection to enumerate class fields and methods in order to do some automation in a web application. I am also abstracting this so that I could pass in any class.
Is there a way I could somehow pass in the type directly to a function to enumerate on rather than an instance of the type?
I would like the caller side to look like this:
var m = new MyClass(AClassOfSomeTypeIDefined);
I would like to avoid creating an instance as that is misleading to anyone who might use the class (as the instance isn't directly used).
using System;
public void UseType(Type t) {
// do something with t using reflection techniques - e.g.
Console.WriteLine("compat with int? {0}", typeof(int).IsAssignableFrom(t));
}
Call it with C# typeof keyword and the data type you want to pass.
// Examples...
UseType( typeof(int) );
UseType( typeof(System.Int32) );
UseType( typeof(System.Windows.Controls.Button) );
UseType( typeof(IDisposable) );
UseType( typeof(WhateverTypeYouWant) );
System.Type is one of the cornerstones of reflection as you already know, so run with it.
Other notes
Depending on what you want to do with the type, the following peripheral details might be useful.
To create an instance of a Type at runtime without having used the new keyword at compile time, use the System.Activator class. e.g.
// Create a List of strings like: new List<string>();
var list = (List<string>) Activator.CreateInstance( typeof(List<string>) );
yes just use the Type of your class. There's two basic ways to get the type:
Foo foo = new Foo();
Type myType = foo.GetType();
Type myTyp2 = typeof(Foo);
You can use GetType() if you only know the type at runtime (more common with reflection), or typeof() if you know the type at compile time already.
In your example this would be i.e.
var m = new MyClass(typeof(Foo));
You can pass a Type object just like any other parameter.
class MyClass
{
public MyClass(Type yourType)
{
// do as you please with yourType
}
}
The call it:
var m = new MyClass(typeof(YourType));

How to dynamcially call a generic method based on a mapping in a dictionary?

I have a method
String Foo<T> where T: WebControl
Now I do have a string like "hyperlink". What is want is to call Foo<Hyperlink> based on a mapping from the string to the generic.
How does the dictionary have to look like?
It ain't:
private Dictionary<string, Type> _mapping = new Dictionary<string, Type>()
{
{"hyperlink", typeof(HyperLink)}
};
I want to access it like Foo<_mapping[mystring]> is that possible? If yes, how must be dictionary look like?
Edit: Accepted Solution
String _typename = "hyperlink";
MethodInfo _mi = typeof(ParserBase).GetMethod("Foo");
Type _type = _mapping[_typename];
MethodInfo _mig = _mi.MakeGenericMethod(_type);
return (String)_mig.Invoke(this, new object[] { _props }); // where _props is a dictionary defined elsewhere
// note that the first parameter for invoke is "this", due to my method Foo is not static
What you want isn't possible, as that would be runtime (e.g. the dictionary could contain anything later).
If you want to manually generate it via runtime, you can do so, but you won't get the compile-time checking C# has on generics. You can to this via MethodInfo.MakeGenericMethod.
Like this:
var m = typeof(MyClass);
var mi = ex.GetMethod("Foo");
var mig = mi.MakeGenericMethod(_mapping["hyperlink"]);
//Invoke it
mig .Invoke(null, args);
It isn't possible this way. Generics supports only compile-tipe binding.
No, you can't do that. Your generic type wants to create itself at compile time but it doesn't know what type it is til runtime. You can, however, use reflection.
Type untypedGeneric = typeof(Foo<>);
Type typedGeneric = untypedGeneric.MakeGenericType(_mapping[mystring]);

Categories

Resources