TypeConverter cannot convert from System.String - c#

I'm trying to convert a string to its corresponding class (i.e. "true" to true). And I get "TypeConverter cannot convert from System.String". The value passed is "true".
Am I calling the method in the wrong way?
public static T ToClass<T>(this IDictionary<string, string> source) where T : class, new()
{
Type type = typeof(T);
T ret = new T();
foreach (var keyValue in source)
{
type.GetProperty(keyValue.Key).SetValue(ret, keyValue.Value.ToString().TestParse<T>(), null);
}
return ret;
}
public static T TestParse<T>(this string value)
{
return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(value);
}

The problem is that the T you pass to the TestParse method is not the type bool but the type of the class you want to create. If you change the line to
public static bool TestParse(this string value)
{
return (bool)TypeDescriptor.GetConverter(typeof(bool)).ConvertFromString(value);
}
It works for the bool case but obviously not for other cases. You need to get the type of the property you want to set via reflection and pass it to the TestParse method.
public static T ToClass<T>(this IDictionary<string, string> source) where T : class, new()
{
Type type = typeof(T);
T ret = new T();
foreach (var keyValue in source)
{
var propertyInfo = type.GetProperty(keyValue.Key);
propertyInfo.SetValue(ret, keyValue.Value.ToString().TestParse(propertyInfo.PropertyType), null);
}
return ret;
}
public static object TestParse(this string value, Type type)
{
return TypeDescriptor.GetConverter(type).ConvertFromString(value);
}
I would also change the TestParse method from an Extension Method to a normal method because it feels kinda weird

Do it as it was done in this answer:
return (T)Convert.ChangeType(value, typeof(T));
where T is the target Type and value is of Type string
EDIT: this only works for IConvertible implementers...

Related

How to check a reflected property's default value [duplicate]

I'm using reflection to loop through a Type's properties and set certain types to their default. Now, I could do a switch on the type and set the default(Type) explicitly, but I'd rather do it in one line. Is there a programmatic equivalent of default?
In case of a value type use Activator.CreateInstance and it should work fine.
When using reference type just return null
public static object GetDefault(Type type)
{
if(type.IsValueType)
{
return Activator.CreateInstance(type);
}
return null;
}
In the newer version of .net such as .net standard, type.IsValueType needs to be written as type.GetTypeInfo().IsValueType
Why not call the method that returns default(T) with reflection ? You can use GetDefault of any type with:
public object GetDefault(Type t)
{
return this.GetType().GetMethod("GetDefaultGeneric").MakeGenericMethod(t).Invoke(this, null);
}
public T GetDefaultGeneric<T>()
{
return default(T);
}
You can use PropertyInfo.SetValue(obj, null). If called on a value type it will give you the default. This behavior is documented in .NET 4.0 and in .NET 4.5.
If you're using .NET 4.0 or above and you want a programmatic version that isn't a codification of rules defined outside of code, you can create an Expression, compile and run it on-the-fly.
The following extension method will take a Type and get the value returned from default(T) through the Default method on the Expression class:
public static T GetDefaultValue<T>()
{
// We want an Func<T> which returns the default.
// Create that expression here.
Expression<Func<T>> e = Expression.Lambda<Func<T>>(
// The default value, always get what the *code* tells us.
Expression.Default(typeof(T))
);
// Compile and return the value.
return e.Compile()();
}
public static object GetDefaultValue(this Type type)
{
// Validate parameters.
if (type == null) throw new ArgumentNullException("type");
// We want an Func<object> which returns the default.
// Create that expression here.
Expression<Func<object>> e = Expression.Lambda<Func<object>>(
// Have to convert to object.
Expression.Convert(
// The default value, always get what the *code* tells us.
Expression.Default(type), typeof(object)
)
);
// Compile and return the value.
return e.Compile()();
}
You should also cache the above value based on the Type, but be aware if you're calling this for a large number of Type instances, and don't use it constantly, the memory consumed by the cache might outweigh the benefits.
Why do you say generics are out of the picture?
public static object GetDefault(Type t)
{
Func<object> f = GetDefault<object>;
return f.Method.GetGenericMethodDefinition().MakeGenericMethod(t).Invoke(null, null);
}
private static T GetDefault<T>()
{
return default(T);
}
This is optimized Flem's solution:
using System.Collections.Concurrent;
namespace System
{
public static class TypeExtension
{
//a thread-safe way to hold default instances created at run-time
private static ConcurrentDictionary<Type, object> typeDefaults =
new ConcurrentDictionary<Type, object>();
public static object GetDefaultValue(this Type type)
{
return type.IsValueType
? typeDefaults.GetOrAdd(type, Activator.CreateInstance)
: null;
}
}
}
The chosen answer is a good answer, but be careful with the object returned.
string test = null;
string test2 = "";
if (test is string)
Console.WriteLine("This will never be hit.");
if (test2 is string)
Console.WriteLine("Always hit.");
Extrapolating...
string test = GetDefault(typeof(string));
if (test is string)
Console.WriteLine("This will never be hit.");
I do the same task like this.
//in MessageHeader
private void SetValuesDefault()
{
MessageHeader header = this;
Framework.ObjectPropertyHelper.SetPropertiesToDefault<MessageHeader>(this);
}
//in ObjectPropertyHelper
public static void SetPropertiesToDefault<T>(T obj)
{
Type objectType = typeof(T);
System.Reflection.PropertyInfo [] props = objectType.GetProperties();
foreach (System.Reflection.PropertyInfo property in props)
{
if (property.CanWrite)
{
string propertyName = property.Name;
Type propertyType = property.PropertyType;
object value = TypeHelper.DefaultForType(propertyType);
property.SetValue(obj, value, null);
}
}
}
//in TypeHelper
public static object DefaultForType(Type targetType)
{
return targetType.IsValueType ? Activator.CreateInstance(targetType) : null;
}
Equivalent to Dror's answer but as an extension method:
namespace System
{
public static class TypeExtensions
{
public static object Default(this Type type)
{
object output = null;
if (type.IsValueType)
{
output = Activator.CreateInstance(type);
}
return output;
}
}
}
The Expressions can help here:
private static Dictionary<Type, Delegate> lambdasMap = new Dictionary<Type, Delegate>();
private object GetTypedNull(Type type)
{
Delegate func;
if (!lambdasMap.TryGetValue(type, out func))
{
var body = Expression.Default(type);
var lambda = Expression.Lambda(body);
func = lambda.Compile();
lambdasMap[type] = func;
}
return func.DynamicInvoke();
}
I did not test this snippet, but i think it should produce "typed" nulls for reference types..
Slight adjustments to #Rob Fonseca-Ensor's solution: The following extension method also works on .Net Standard since I use GetRuntimeMethod instead of GetMethod.
public static class TypeExtensions
{
public static object GetDefault(this Type t)
{
var defaultValue = typeof(TypeExtensions)
.GetRuntimeMethod(nameof(GetDefaultGeneric), new Type[] { })
.MakeGenericMethod(t).Invoke(null, null);
return defaultValue;
}
public static T GetDefaultGeneric<T>()
{
return default(T);
}
}
...and the according unit test for those who care about quality:
[Fact]
public void GetDefaultTest()
{
// Arrange
var type = typeof(DateTime);
// Act
var defaultValue = type.GetDefault();
// Assert
defaultValue.Should().Be(default(DateTime));
}
/// <summary>
/// returns the default value of a specified type
/// </summary>
/// <param name="type"></param>
public static object GetDefault(this Type type)
{
return type.IsValueType ? (!type.IsGenericType ? Activator.CreateInstance(type) : type.GenericTypeArguments[0].GetDefault() ) : null;
}
This should work:
Nullable<T> a = new Nullable<T>().GetValueOrDefault();
If you already create an object, you can try...
var yourObj = new yourObj();
var properties = yourObj.GetType().GetProperties();
foreach (var p in properties)
{
// you can get default value for each property
var defaultValue = p.GetValue(yourObj, null);
}

How can I supply a type in a generic method to use for casting?

I have these two methods:
private int GetInt(string key)
{
try
{
return (int)_data[key];
} catch (KeyNotFoundException)
{
return 0;
}
}
private int? GetNullableInt(string key)
{
try
{
return (int?)_data[key];
} catch (KeyNotFoundException)
{
return null;
}
}
But, I would like to create one generic method, to prevent code duplication, along the lines of:
private T Get<T>(string key, T type)
{
try
{
return (T)_data[key];
} catch (KeyNotFoundException)
{
return default(T);
}
}
However, I don't seem to get this right. The method compiles, but I have no idea how to call it:
Get("myKey", typeof(int));
doesn't work.
Get("myKey", int);
would be my preference, but that seems to be invalid syntax.
I would suggest using generic dictionaries and en extension method. i.e. something like:
public static T GetOrDefault<TKey, T>(this IDictionary<TKey, T> self, TKey key)
{
if (self.TryGetValue(key, out var value))
{
return value;
}
return default;
}
public static T? GetOrNullable<TKey, T>(this IDictionary<TKey, T> self, TKey key) where T : struct
{
if (self.TryGetValue(key, out var value))
{
return value;
}
return null;
}
And call it like
var dict = new Dictionary<string, int>();
var valueOrDefault = dict.GetOrDefault("test");
var valueOrNull = dict.GetOrNullable("test");
This lets the compiler infer the type arguments.
If you really need non generic dictionaries, or a Dictionary<string, object> you also need to consider what will happen if the object is not the type you requested.

Convert Strings to Type Instances

have you any alternative to these code, i want a more generic code
I tried Convert class but with no success
public object convert(Type type, string value)
{
object r = null;
if (type == typeof(bool))
{
r = bool.Parse(value);
}
else if (type == typeof(int))
{
r = int.Parse(value);
}
else if (type == typeof(string))
{
r = value;
}
return r;
}
var conv = TypeDescriptor.GetConverter(type);
return conv.ConvertFromInvariantString(value);
Other conversion operations exist if you don't want "invariant". It depends on your needs. See also ConvertFromString if you want locale settins to apply, etc.
You mention you have tried the Convert class, but have you also tried Convert.ChangeType(value, type)? What where the problems you ran in to?
How about creating a dictionary Dictionary<Type, Func<string, object>>?
Maybe something like this:
public static class MyConverter
{
private static Dictionary<Type, Func<string, object>> _Converters;
static MyConverter()
{
_Converters = new Dictionary<Type, Func<string, object>>();
// Add converter from available method
_Converters.Add(typeof(double), MySpecialConverter);
// Add converter as lambda
_Converters.Add(typeof(bool), (text) => bool.Parse(text));
// Add converter from complex lambda
_Converters.Add(typeof(int), (text) =>
{
if (String.IsNullOrEmpty(text))
{
throw new ArgumentNullException("text");
}
return int.Parse(text);
});
}
private static object MySpecialConverter(string text)
{
return double.Parse(text);
}
public static object Convert(Type type, string value)
{
Func<string, object> converter;
if (!_Converters.TryGetValue(type, out converter))
{
throw new ArgumentException("No converter for type " + type.Name + " available.");
}
return converter(value);
}
}
Convert.ChangeType() method doesn't convert to null-able types, Guid, Enums etc. This implementation of ChangeType will convert it all.

InvalidCastException with custom generic TypeConverter for use within MCV environment, need fix

I need a TypeConverter that, idealy, translates a String to a type safe enum class (CountryIso) without having to write a converter for every type safe enum I'm about to make.
While I managed to get the following to work:
CountryIso cI = (CountryIso) "1";
I just can't get it to work with generics! The following sample doesn't work, but why?
TypeDescriptor.AddProvider(new ExplicitCastDescriptionProvider<CountryIso>(), typeof(CountryIso));
var descriptor = TypeDescriptor.GetConverter(typeof(CountryIso));
var result = descriptor.ConvertFrom("1");
I currently have a generic TypeConverter implementation:
public class ExplicitCastConverter<T>: TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
// Always true: the type determines if a cast is available or not
return true;
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
String dummy = (String) value;
//CountryIso tst = (CountryIso) value; // Allowed, no problem casting
//CountryIso tst = (CountryIso) dummy; // Allowed, no problem casting
//var dum_001 = (T) ((String) value); // Does not compile
//var dumdum = (T) value; // Invalid case exception
//var hoot = (T) Convert.ChangeType(value, typeof (T)); // Invalid cast exception
return null;
}
}
The Provider is as follows:
//thanks: http://groups.google.com/group/wpf-disciples/browse_thread/thread/9f7bb40b7413fcd
public class ExplicitCastDescriptionProvider<T> : TypeDescriptionProvider //where T:TypeSafeEnum
{
public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
{
return new ImplicitCastDescription<T>();
}
}
public class ImplicitCastDescription<T>: CustomTypeDescriptor //where T:TypeSafeEnum
{
public override TypeConverter GetConverter()
{
return new ExplicitCastConverter<T>();
}
}
I have a type safe enum implementation CountryIso (thanks StackOverflow!):
public sealed class CountryIso: TypeSafeEnum
{
private static readonly Dictionary<int, CountryIso> InstanceDict = new Dictionary<int, CountryIso>();
public static readonly CountryIso NL = new CountryIso(1, "NL", "Netherlands");
public static readonly CountryIso BE = new CountryIso(2, "BE", "Belgium");
private CountryIso(int value, String name, String description): base(value,name,description)
{
InstanceDict.Add(value, this);
}
public static Dictionary<int, CountryIso> Instances
{
get { return new Dictionary<int, CountryIso>(InstanceDict); }
}
public static explicit operator CountryIso(String i)
{
int index;
return Int32.TryParse(i,out index) ? InstanceDict[index] : null;
}
}
Which inherits from TypeSafeEnum:
public class TypeSafeEnum
{
protected TypeSafeEnum(int value, String name, String description)
{
Name = name;
Value = value;
Description = description;
}
public int Value{ get; private set; }
public String Name { get; private set; }
public String Description { get; private set; }
}
One option: use reflection
The problem lies with the static nature of the CountryIso members and (mostly) the casting operators. This prevents any blueprint definition enabling a generic typeconverter to know it can cast the CountryIso type safe enum. Also, you cannot cast 'down': a TypeSafeEnum can never become a CountryIso. Which is logical, but doesn't help.
[ Using reflection ]
Introduced a generic interface defining a casting method:
public interface ICast<out T>
{
T Cast(String obj);
}
Apply interface to CountryIso
public sealed class CountryIso: TypeSafeEnum , ICast<CountryIso>
Add interface as contstraint to the converter class
public class ExplicitCastConverter<T>: TypeConverter where T: ICast<T>
Add a (non-static) cast method to my CountryIso:
public new CountryIso Cast(String obj)
{
int index;
return Int32.TryParse(obj, out index) ? InstanceDict[index] : null;
}
Added a default static member to my type-safe-enum:
private static readonly CountryIso DefaultTypeSafeEnum = new CountryIso(
-1,
null,
null
);
Implement the ConvertFrom(..) in the Converter class:
T defaultMember = (T)typeof(T).GetField(
"DefaultTypeSafeEnum",
BindingFlags.NonPublic | BindingFlags.Static
).GetValue(null);
return defaultMember.Cast((String) value);
[ Type safe enum security ]
It's still possible to create & insert new instances of CountryIso via reflection (especially when using the InstanceDict for easy instance access!) Some sample code:
ConstructorInfo ci = typeof (T).GetConstructor(
BindingFlags.NonPublic|BindingFlags.Instance,
null,
CallingConventions.Standard,
new [] {typeof (int), typeof (String), typeof (String)},
new ParameterModifier[0]
);
CountryIso countryIso = (CountryIso) ci.Invoke(new object[]{30, "ZB", "Zanzibar"});
I now consider the usage of the private InstanceDict member a security hole (not a big one, since I'm not programming an API for the outside world, but still...)

How to get the type of T from a member of a generic class or method

Let's say I have a generic member in a class or method, like so:
public class Foo<T>
{
public List<T> Bar { get; set; }
public void Baz()
{
// get type of T
}
}
When I instantiate the class, the T becomes MyTypeObject1, so the class has a generic list property: List<MyTypeObject1>. The same applies to a generic method in a non-generic class:
public class Foo
{
public void Bar<T>()
{
var baz = new List<T>();
// get type of T
}
}
I would like to know what type of objects the list of my class contains. So what type of T does the list property called Bar or the local variable baz contain?
I cannot do Bar[0].GetType(), because the list might contain zero elements. How can I do it?
If I understand correctly, your list has the same type parameter as the container class itself. If this is the case, then:
Type typeParameterType = typeof(T);
If you are in the lucky situation of having object as a type parameter, see Marc's answer.
(note: I'm assuming that all you know is object or IList or similar, and that the list could be any type at runtime)
If you know it is a List<T>, then:
Type type = abc.GetType().GetGenericArguments()[0];
Another option is to look at the indexer:
Type type = abc.GetType().GetProperty("Item").PropertyType;
Using new TypeInfo:
using System.Reflection;
// ...
var type = abc.GetType().GetTypeInfo().GenericTypeArguments[0];
With the following extension method you can get away without reflection:
public static Type GetListType<T>(this List<T> _)
{
return typeof(T);
}
Or more general:
public static Type GetEnumeratedType<T>(this IEnumerable<T> _)
{
return typeof(T);
}
Usage:
List<string> list = new List<string> { "a", "b", "c" };
IEnumerable<string> strings = list;
IEnumerable<object> objects = list;
Type listType = list.GetListType(); // string
Type stringsType = strings.GetEnumeratedType(); // string
Type objectsType = objects.GetEnumeratedType(); // BEWARE: object
Try
list.GetType().GetGenericArguments()
If you don’t need the whole Type variable and just want to check the type, you can easily create a temporary variable and use the is operator.
T checkType = default(T);
if (checkType is MyClass)
{}
The following works for me. Where myList is some unknown kind of list.
IEnumerable myEnum = myList as IEnumerable;
Type entryType = myEnum.AsQueryable().ElementType;
You can use this one for the return type of a generic list:
public string ListType<T>(T value)
{
var valueType = value.GetType().GenericTypeArguments[0].FullName;
return valueType;
}
The GetGenericArgument() method has to be set on the Base Type of your instance (whose class is a generic class myClass<T>). Otherwise, it returns a type[0].
Example:
Myclass<T> instance = new Myclass<T>();
Type[] listTypes = typeof(instance).BaseType.GetGenericArguments();
I use this extension method to accomplish something similar:
public static string GetFriendlyTypeName(this Type t)
{
var typeName = t.Name.StripStartingWith("`");
var genericArgs = t.GetGenericArguments();
if (genericArgs.Length > 0)
{
typeName += "<";
foreach (var genericArg in genericArgs)
{
typeName += genericArg.GetFriendlyTypeName() + ", ";
}
typeName = typeName.TrimEnd(',', ' ') + ">";
}
return typeName;
}
public static string StripStartingWith(this string s, string stripAfter)
{
if (s == null)
{
return null;
}
var indexOf = s.IndexOf(stripAfter, StringComparison.Ordinal);
if (indexOf > -1)
{
return s.Substring(0, indexOf);
}
return s;
}
You use it like this:
[TestMethod]
public void GetFriendlyTypeName_ShouldHandleReallyComplexTypes()
{
typeof(Dictionary<string, Dictionary<string, object>>).GetFriendlyTypeName()
.ShouldEqual("Dictionary<String, Dictionary<String, Object>>");
}
This isn't quite what you're looking for, but it's helpful in demonstrating the techniques involved.
Consider this:
I use it to export 20 typed lists by the same way:
private void Generate<T>()
{
T item = (T)Activator.CreateInstance(typeof(T));
((T)item as DemomigrItemList).Initialize();
Type type = ((T)item as DemomigrItemList).AsEnumerable().FirstOrDefault().GetType();
if (type == null)
return;
if (type != typeof(account)) // Account is listitem in List<account>
{
((T)item as DemomigrItemList).CreateCSV(type);
}
}
You can get the type of "T" from any collection type that implements IEnumerable<T> with the following:
public static Type GetCollectionItemType(Type collectionType)
{
var types = collectionType.GetInterfaces()
.Where(x => x.IsGenericType
&& x.GetGenericTypeDefinition() == typeof(IEnumerable<>))
.ToArray();
// Only support collections that implement IEnumerable<T> once.
return types.Length == 1 ? types[0].GetGenericArguments()[0] : null;
}
Note that it doesn't support collection types that implement IEnumerable<T> twice, e.g.
public class WierdCustomType : IEnumerable<int>, IEnumerable<string> { ... }
I suppose you could return an array of types if you needed to support this...
Also, you might also want to cache the result per collection type if you're doing this a lot (e.g. in a loop).
Using 3dGrabber's solution:
public static T GetEnumeratedType<T>(this IEnumerable<T> _)
{
return default(T);
}
//and now
var list = new Dictionary<string, int>();
var stronglyTypedVar = list.GetEnumeratedType();
public bool IsCollection<T>(T value){
var valueType = value.GetType();
return valueType.IsArray() || typeof(IEnumerable<object>).IsAssignableFrom(valueType) || typeof(IEnumerable<T>).IsAssignableFrom(valuetype);
}
If you want to know a property's underlying type, try this:
propInfo.PropertyType.UnderlyingSystemType.GenericTypeArguments[0]
This is how I did it:
internal static Type GetElementType(this Type type)
{
// Use type.GenericTypeArguments if it exists
if (type.GenericTypeArguments.Any())
return type.GenericTypeArguments.First();
return type.GetRuntimeProperty("Item").PropertyType);
}
Then call it like this:
var item = Activator.CreateInstance(iListType.GetElementType());
Or
var item = Activator.CreateInstance(Bar.GetType().GetElementType());
try this.
if (typeof(T) == typeof(Person))
Type:
type = list.AsEnumerable().SingleOrDefault().GetType();

Categories