Convert a user inputted string to a class that gets cast - c#

I have a string that gets inputted by a user. The string can look like: Button.Minimize or Hyperlink.SomeLink
I need to take the first part of the string and convert it to a class that is located in a dll library. Then I need to cast that as a type.
I have seen countless examples on here but none that show how to convert the string to ANY type. All the examples I have seen are when you know which type you want to convert the string to beforehand.
Basically I need a method that converts a string to any kind of class name. Like: Button, HyperLink, etc...
public static void ClickOn(Step step)
{
string[] kvp = step.Element.Split('.');
var type = kvp[0];
var element = kvp[1];
GetType(type);
var path = MainWin.Get<type>(element); //inputted string would be cast in this line where you see <type>
path.Click();
}
public static Type GetType(string typeName)
{
Type get = Type.GetType(typeName, true);
Object type = (Activator.CreateInstance(get));
return type;
}

If you mean cast as in (string)anObject then there is no way to do this. Casting in this way is a compile time activity that gives the compiler awareness about the type that it is working with. Since what you are describing is essentially a runtime activity, there is nothing that the compiler can do to help you at this point.
If you write a different question that describes the problem you are trying to solve with this in more detail (or change this question), then someone can probably suggest a way to accomplish what you want.

Define interface called IClickablewith a Click method and make all the classes implement that interface. Rename your method GetType to GetClickableObject and make that method return a IClickable. Something like this:
public static void ClickOn(Step step)
{
// get type
string fullClassType = ...;
IClickable obj = MainWin.GetClickableObject(fullClassType);
obj.Click();
}
public static IClickable GetClickableObject(string typeName)
{
Type get = Type.GetType(typeName, true);
IClickable obj = (IClickable)Activator.CreateInstance(get);
return obj;
}
}
interface IClickable
{
void Click();
}
class Button : IClickable
{
//...
}

Related

Create an instance of C# generic class [duplicate]

The title is kind of obscure. What I want to know is if this is possible:
string typeName = <read type name from somwhere>;
Type myType = Type.GetType(typeName);
MyGenericClass<myType> myGenericClass = new MyGenericClass<myType>();
Obviously, MyGenericClass is described as:
public class MyGenericClass<T>
Right now, the compiler complains that 'The type or namespace 'myType' could not be found." There has got to be a way to do this.
You can't do this without reflection. However, you can do it with reflection. Here's a complete example:
using System;
using System.Reflection;
public class Generic<T>
{
public Generic()
{
Console.WriteLine("T={0}", typeof(T));
}
}
class Test
{
static void Main()
{
string typeName = "System.String";
Type typeArgument = Type.GetType(typeName);
Type genericClass = typeof(Generic<>);
// MakeGenericType is badly named
Type constructedClass = genericClass.MakeGenericType(typeArgument);
object created = Activator.CreateInstance(constructedClass);
}
}
Note: if your generic class accepts multiple types, you must include the commas when you omit the type names, for example:
Type genericClass = typeof(IReadOnlyDictionary<,>);
Type constructedClass = genericClass.MakeGenericType(typeArgument1, typeArgument2);
Unfortunately no there is not. Generic arguments must be resolvable at Compile time as either 1) a valid type or 2) another generic parameter. There is no way to create generic instances based on runtime values without the big hammer of using reflection.
Some additional how to run with scissors code. Suppose you have a class similar to
public class Encoder() {
public void Markdown(IEnumerable<FooContent> contents) { do magic }
public void Markdown(IEnumerable<BarContent> contents) { do magic2 }
}
Suppose at runtime you have a FooContent
If you were able to bind at compile time you would want
var fooContents = new List<FooContent>(fooContent)
new Encoder().Markdown(fooContents)
However you cannot do this at runtime. To do this at runtime you would do along the lines of:
var listType = typeof(List<>).MakeGenericType(myType);
var dynamicList = Activator.CreateInstance(listType);
((IList)dynamicList).Add(fooContent);
To dynamically invoke Markdown(IEnumerable<FooContent> contents)
new Encoder().Markdown( (dynamic) dynamicList)
Note the usage of dynamic in the method call. At runtime dynamicList will be List<FooContent> (additionally also being IEnumerable<FooContent>) since even usage of dynamic is still rooted to a strongly typed language the run time binder will select the appropriate Markdown method. If there is no exact type matches, it will look for an object parameter method and if neither match a runtime binder exception will be raised alerting that no method matches.
The obvious draw back to this approach is a huge loss of type safety at compile time. Nevertheless code along these lines will let you operate in a very dynamic sense that at runtime is still fully typed as you expect it to be.
My requirements were slightly different, but will hopefully help someone. I needed to read type from a config and instantiate the generic type dynamically.
namespace GenericTest
{
public class Item
{
}
}
namespace GenericTest
{
public class GenericClass<T>
{
}
}
Finally, here is how you call it. Define the type with a backtick.
var t = Type.GetType("GenericTest.GenericClass`1[[GenericTest.Item, GenericTest]], GenericTest");
var a = Activator.CreateInstance(t);
If you know what types will be passed you can do this without reflection. A switch statement would work. Obviously, this would only work in a limited number of cases, but it'll be much faster than reflection.
public class Type1 { }
public class Type2 { }
public class Generic<T> { }
public class Program
{
public static void Main()
{
var typeName = nameof(Type1);
switch (typeName)
{
case nameof(Type1):
var type1 = new Generic<Type1>();
// do something
break;
case nameof(Type2):
var type2 = new Generic<Type2>();
// do something
break;
}
}
}
In this snippet I want to show how to create and use a dynamically created list. For example, I'm adding to the dynamic list here.
void AddValue<T>(object targetList, T valueToAdd)
{
var addMethod = targetList.GetType().GetMethod("Add");
addMethod.Invoke(targetList, new[] { valueToAdd } as object[]);
}
var listType = typeof(List<>).MakeGenericType(new[] { dynamicType }); // dynamicType is the type you want
var list = Activator.CreateInstance(listType);
AddValue(list, 5);
Similarly you can invoke any other method on the list.

Getting a value from a generic method without supplying the type

I was trying to create a class were one of the properties was generic without the class itself being generic. I discover that you can't do that; generic properties aren't allowed. A bit of digging here too me to the thread Making a generic property were I found a work around that works nicely for me.
Subsequently, I ended up with this class...
[Serializable]
public class ConfigurationItem
{
private readonly Type type;
public string Description { get; set; }
public IDictionary<string, ConfigurationItem> Items { get; private set; }
public string Name { get; set; }
public string Summary { get; set; }
public object Value { get; private set; }
public ConfigurationItem(string name, Type type = null, object value = null)
{
this.Name = name;
this.type = type ?? typeof(string);
this.Value = value;
Items = new Dictionary<string, ConfigurationItem>();
}
public string Export()
{
return JsonConvert.SerializeObject(this);
}
public T GetValue<T>()
{
return (T)Convert.ChangeType(Value, type);
}
}
Now the only issue I have is that if I want to get the value, properly cast, I have to supply the type when I call GetValue(). Instinctively, I can't help but feel, given that the class knows the type that should be returned, it should be possible for me to construct a GetValue() method that doesn't require any additional information from me.
I can't figure out how.
I did find the thread Getting a generic method to infer the type parameter from the runtime type which appears to suggest that it is possible, but I understand very little about Reflection and couldn't make any sense of what was being said.
Is there a way of constructing a GetType() method that doesn't require that I supply the generic type? And can you explain it in a way that my feeble brain can comprehend it?
EDIT
A number of people have actually pointed out that really I don't need to do this anyway, nonetheless as a learning exercise I followed up the suggestion from #ShoaibShakeel to look at the C# dynamic type and came up with these additional methods...
public dynamic GetValue()
{
return typeof(ConfigurationItem)
.GetMethod("GetReturnValue", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
.MakeGenericMethod(type)
.Invoke(this, new object[] { });
}
private T GetReturnValue<T>()
{
return (T)Convert.ChangeType(Value, type);
}
Instinctively, I can't help but feel, given that the class knows the type that should be returned
While it is true that the Value object knows its own type, this information is only available at runtime though (once there is an actual object that has a type). So in order to have type information at compile time, you need to supply the necessary information. After all, it’s impossible to know statically what object is being assigned there.
But assuming that GetValue() was able to return the typed object automatically, what would you want to do with it?
var x = configurationItem.GetValue();
So what type should x be of, and what would you want to do with it afterwards? Do you only want to print it or something? Then object is enough. Do you want to calculate something with it? Then you would already require that it’s an int, or a float or something, so you would need an actual static type—which is why you would have to supply that type information.
Just because the return type is object that does not mean that the object itself loses the type information. A string assigned to an object property will still be a string, even if you retrieve it much later. And if you expect a string and want to do something with it, then you can surely just cast it to a string.
No.
The compiler cannot infer the type from the variable it is assigned to since it is ambiguous, especially in large inheritance trees.
Consider the line
object o = configurationItem.GetValue<int>();
int may be a valid conversion for your value but object isn't, since objectdoes not implement the IConvertible interface (required by Convert.ChangeType().
I was able to get my class to return a value, cast correctly, using reflection and dynamics using the following additions to my original class.
public dynamic GetValue()
{
return typeof(ConfigurationItem)
.GetMethod("GetReturnValue", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
.MakeGenericMethod(type)
.Invoke(this, new object[] { });
}
private T GetReturnValue<T>()
{
return (T)Convert.ChangeType(Value, type);
}

How to write a method to accept a type as a parameter and use it within the method body to cast another variable into that passed type?

What I want is to have a method that accepts a type as a parameter and cast a variable into that type within the method in C#
as an example I want to pass a UI element to this helper method and extract its DataContext's (which is bound dynamically at runtime) Description. I want to use this method in a more generalized manner so that I can pass in the DataContext's type also.
private String GetDescription(FrameworkElement element, Type type) {
return (element.DataContext as type).Description;
//or
//return ((type)element.DataContext).Description;
}
both the ways it ends up with a compile time error.
I tried using generics as well but it was not successful as i might not understood properly.
It would be really great if someone could explain how to do this in a simple manner.
Write a interface and implement it for your classes:
public interface IDescribable
{
string Description{get;}
}
Implement this object on your desired classes:
public class MyClass:IDescribable
{
// other members
public string Description{get; set;}
}
Then you could even write an extension method to extract the string:
public static string GetDescription(this FrameworkElement element)
{
var contextData= element.DataContext as IDescribable;
return contextData!=null
? contextData.Description
:"";
}
Or if you don't want implement interface use reflection:
private string GetDescription(FrameworkElement element)
{
var decProp= element.DataContext.GetType().GetProperty("Description");
return decProp!=null
?decProp.GetValue(element.DataContext)
:"";
}

How do I get ConfigurationSection property as a System.Type

i want to define a custom configuration section and have a property not yield a string but a system.type (or null if the user types in a load of rubbish)
e.g.:
<myCustomConfig myAnnoyingType="System.String" />
in the C# (in the current real world)
[ConfigurationProperty("myAnnoyingType")]
public string MyAnnoyingType
{
get { return (string)this["myAnnoyingType"]; }
}
// else where in the app
var stringType = thatConfig.MyAnnoyingType
var actualType = Type.GetType(stringType);
// wow that was boring.
in the C# (in an ideal world)
[ConfigurationProperty("myAnnoyingType")]
public Type MyAnnoyingType
{
get { return (Type)this["myAnnoyingType"]; }
}
What I want is NOT to have to keep the item as a string in the C# and then convert that into a Type in the application; i'd like this to be done automatically as part of the responsibility of the ConfigurationManager.
Is this possible? I'm OK to use a TypeConverter if I have to be, it just seems so weak to keep it as a string and then do the type lookup in the application. It's not hard to do, just seems pointless when I know i'm looking for a type, what is the value of having to explicitly do it.
Try using a TypeConverterAttribute that will do the conversion for you. This worked for me.
[ConfigurationProperty("type")]
[TypeConverter(typeof(TypeNameConverter))]
public Type Type
{
get
{
return (System.Type)this["type"];
}
set
{
this["type"] = value;
}
}
First, its better to define a type in your settings using the fully qualified name. This way you get less problems with resolving the Type from the string.
Second, you need to find the Type by it's string name as was already answered in Convert String to Type in C# because it's not possible just cast string to Type.
In your case it would be:
[ConfigurationProperty("myAnnoyingType")]
public Type MyAnnoyingType
{
get { return Type.GetType(this["myAnnoyingType"]); }
}

Generics in c# & accessing the static members of T

My question concerns c# and how to access Static members ... Well I don't really know how to explain it (which kind of is bad for a question isn't it?) I will just give you some sample code:
Class test<T>{
int method1(Obj Parameter1){
//in here I want to do something which I would explain as
T.TryParse(Parameter1);
//my problem is that it does not work ... I get an error.
//just to explain: if I declare test<int> (with type Integer)
//I want my sample code to call int.TryParse(). If it were String
//it should have been String.TryParse()
}
}
So thank you guys for your answers (By the way the question is: how would I solve this problem without getting an error). This probably quite an easy question for you!
Edit: Thank you all for your answers!
Though I think the try - catch phrase is the most elegant, I know from my experience with vb that it can really be a bummer. I used it once and it took about 30 minutes to run a program, which later on only took 2 minutes to compute just because I avoided try - catch.
This is why I chose the switch statement as the best answer. It makes the code more complicated but on the other hand I imagine it to be relatively fast and relatively easy to read. (Though I still think there should be a more elegant way ... maybe in the next language I learn)
Though if you have some other suggestion I am still waiting (and willing to participate)
The problem is that TryParse isn't defined on an interface or base class anywhere, so you can't make an assumption that the type passed into your class will have that function. Unless you can contrain T in some way, you'll run into this a lot.
Constraints on Type Parameters
Short answer, you can't.
Long answer, you can cheat:
public class Example
{
internal static class Support
{
private delegate bool GenericParser<T>(string s, out T o);
private static Dictionary<Type, object> parsers =
MakeStandardParsers();
private static Dictionary<Type, object> MakeStandardParsers()
{
Dictionary<Type, object> d = new Dictionary<Type, object>();
// You need to add an entry for every type you want to cope with.
d[typeof(int)] = new GenericParser<int>(int.TryParse);
d[typeof(long)] = new GenericParser<long>(long.TryParse);
d[typeof(float)] = new GenericParser<float>(float.TryParse);
return d;
}
public static bool TryParse<T>(string s, out T result)
{
return ((GenericParser<T>)parsers[typeof(T)])(s, out result);
}
}
public class Test<T>
{
public static T method1(string s)
{
T value;
bool success = Support.TryParse(s, out value);
return value;
}
}
public static void Main()
{
Console.WriteLine(Test<int>.method1("23"));
Console.WriteLine(Test<float>.method1("23.4"));
Console.WriteLine(Test<long>.method1("99999999999999"));
Console.ReadLine();
}
}
I made a static dictionary holding a delegate for the TryParse method of every type I might want to use. I then wrote a generic method to look up the dictionary and pass on the call to the appropriate delegate. Since every delegate has a different type, I just store them as object references and cast them back to the appropriate generic type when I retrieve them. Note that for the sake of a simple example I have omitted error checking, such as to check whether we have an entry in the dictionary for the given type.
To access a member of a specific class or interface you need to use the Where keyword and specify the interface or base class that has the method.
In the above instance TryParse does not come from an interface or base class, so what you are trying to do above is not possible. Best just use Convert.ChangeType and a try/catch statement.
class test<T>
{
T Method(object P)
{
try {
return (T)Convert.ChangeType(P, typeof(T));
} catch(Exception e) {
return null;
}
}
}
One more way to do it, this time some reflection in the mix:
static class Parser
{
public static bool TryParse<TType>( string str, out TType x )
{
// Get the type on that TryParse shall be called
Type objType = typeof( TType );
// Enumerate the methods of TType
foreach( MethodInfo mi in objType.GetMethods() )
{
if( mi.Name == "TryParse" )
{
// We found a TryParse method, check for the 2-parameter-signature
ParameterInfo[] pi = mi.GetParameters();
if( pi.Length == 2 ) // Find TryParse( String, TType )
{
// Build a parameter list for the call
object[] paramList = new object[2] { str, default( TType ) };
// Invoke the static method
object ret = objType.InvokeMember( "TryParse", BindingFlags.InvokeMethod, null, null, paramList );
// Get the output value from the parameter list
x = (TType)paramList[1];
return (bool)ret;
}
}
}
// Maybe we should throw an exception here, because we were unable to find the TryParse
// method; this is not just a unable-to-parse error.
x = default( TType );
return false;
}
}
The next step would be trying to implement
public static TRet CallStaticMethod<TRet>( object obj, string methodName, params object[] args );
With full parameter type matching etc.
This isn't really a solution, but in certain scenarios it could be a good alternative: We can pass an additional delegate to the generic method.
To clarify what I mean, let's use an example. Let's say we have some generic factory method, that should create an instance of T, and we want it to then call another method, for notification or additional initialization.
Consider the following simple class:
public class Example
{
// ...
public static void PostInitCallback(Example example)
{
// Do something with the object...
}
}
And the following static method:
public static T CreateAndInit<T>() where T : new()
{
var t = new T();
// Some initialization code...
return t;
}
So right now we would have to do:
var example = CreateAndInit<Example>();
Example.PostInitCallback(example);
However, we could change our method to take an additional delegate:
public delegate void PostInitCallback<T>(T t);
public static T CreateAndInit<T>(PostInitCallback<T> callback) where T : new()
{
var t = new T();
// Some initialization code...
callback(t);
return t;
}
And now we can change the call to:
var example = CreateAndInit<Example>(Example.PostInitCallback);
Obviously this is only useful in very specific scenarios. But this is the cleanest solution in the sense that we get compile time safety, there is no "hacking" involved, and the code is dead simple.
Do you mean to do something like this:
Class test<T>
{
T method1(object Parameter1){
if( Parameter1 is T )
{
T value = (T) Parameter1;
//do something with value
return value;
}
else
{
//Parameter1 is not a T
return default(T); //or throw exception
}
}
}
Unfortunately you can't check for the TryParse pattern as it is static - which unfortunately means that it isn't particularly well suited to generics.
The only way to do exactly what you're looking for would be to use reflection to check if the method exists for T.
Another option is to ensure that the object you send in is a convertible object by restraining the type to IConvertible (all primitive types implement IConvertible). This would allow you to convert your parameter to the given type very flexibly.
Class test<T>
{
int method1(IConvertible Parameter1){
IFormatProvider provider = System.Globalization.CultureInfo.CurrentCulture.GetFormat(typeof(T));
T temp = Parameter1.ToType(typeof(T), provider);
}
}
You could also do a variation on this by using an 'object' type instead like you had originally.
Class test<T>
{
int method1(object Parameter1){
if(Parameter1 is IConvertible) {
IFormatProvider provider = System.Globalization.CultureInfo.CurrentCulture.GetFormat(typeof(T));
T temp = Parameter1.ToType(typeof(T), provider);
} else {
// Do something else
}
}
}
Ok guys: Thanks for all the fish. Now with your answers and my research (especially the article on limiting generic types to primitives) I will present you my solution.
Class a<T>{
private void checkWetherTypeIsOK()
{
if (T is int || T is float //|| ... any other types you want to be allowed){
return true;
}
else {
throw new exception();
}
}
public static a(){
ccheckWetherTypeIsOK();
}
}
You probably cant do it.
First of all if it should be possible you would need a tighter bound on T so the typechecker could be sure that all possible substitutions for T actually had a static method called TryParse.
You may want to read my previous post on limiting generic types to primitives. This may give you some pointers in limiting the type that can be passed to the generic (since TypeParse is obviously only available to a set number of primitives ( string.TryParse obviously being the exception, which doesn't make sense).
Once you have more of a handle on the type, you can then work on trying to parse it. You may need a bit of an ugly switch in there (to call the correct TryParse ) but I think you can achieve the desired functionality.
If you need me to explain any of the above further, then please ask :)
Best code: restrict T to ValueType this way:
class test1<T> where T: struct
A "struct" here means a value type.
String is a class, not a value type.
int, float, Enums are all value types.
btw the compiler does not accept to call static methods or access static members on 'type parameters' like in the following example which will not compile :(
class MyStatic { public static int MyValue=0; }
class Test<T> where T: MyStatic
{
public void TheTest() { T.MyValue++; }
}
=> Error 1 'T' is a 'type parameter', which is not valid in the given context
SL.
That is not how statics work. You have to think of statics as sort of in a Global class even if they are are spread across a whole bunch of types. My recommendation is to make it a property inside the T instance that can access the necessary static method.
Also T is an actual instance of something, and just like any other instance you are not able to access the statics for that type, through the instantiated value. Here is an example of what to do:
class a {
static StaticMethod1 ()
virtual Method1 ()
}
class b : a {
override Method1 () return StaticMethod1()
}
class c : a {
override Method1 () return "XYZ"
}
class generic<T>
where T : a {
void DoSomething () T.Method1()
}

Categories