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.
Related
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);
}
Given a generic class Foo<T> with a method public T Convert(string value), I am trying to handle the possibility that T is defined as an array.
For example, T as a simple type:
Foo<int> foo = new Foo<int>();
int bar = foo.Convert("123");
// bar == 123
But also, T as an array:
Foo<int[]> foo = new Foo<int[]>();
int[] bars = foo.Convert("1,2,3");
// bars = [1, 2, 3]
Here is class Foo with an invalid cast that I'm not quite sure how to resolve.
public class Foo<T>
{
public T Convert(string value)
{
Type t = typeof(T);
if (t.IsArray)
{
string[] values = value.Split(',');
Type elementType = t.GetElementType();
// this cast is invalid
return (T)values.Select(v => elementType.IsEnum ? Enum.Parse(elementType, v, true) : ChangeType(v, elementType)).ToArray();
}
else
{
return (T)ChangeType(value, t);
}
}
private object ChangeType(string value, Type type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
{
if (value == null)
{
return default;
}
type = Nullable.GetUnderlyingType(type);
}
return System.Convert.ChangeType(value, type);
}
}
You are not really using the features of generics here, except getting the type via typeof(T). So a solution without generics would be:
public class Foo
{
public object Convert(string value, Type t)
{
if (t.IsArray)
{
string[] values = value.Split(',');
Type elementType = t.GetElementType();
var array = Array.CreateInstance(elementType, values.Length);
for (var i = 0; i < values.Length; i++)
{
array.SetValue(elementType.IsEnum ? Enum.Parse(elementType, values[i], true) : ChangeType(values[i], elementType), i);
}
return array;
}
else
{
return ChangeType(value, t);
}
}
private object ChangeType(string value, Type type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
{
if (value == null)
{
return default;
}
type = Nullable.GetUnderlyingType(type);
}
return System.Convert.ChangeType(value, type);
}
}
Note that I use Array.CreateInstance to create e.g. a proper int[] instead of the object[] created by your values.Select(v => elementType.IsEnum ? Enum.Parse(elementType, v, true) : ChangeType(v, elementType)).ToArray().
If you want, you can still have a generic version on top of it:
public class Foo<T> : Foo
{
public T Convert(string value)
{
return (T)Convert(value, typeof(T));
}
}
Why not keep your impl that understands Foo<int> and use it to make an array:
int[] bars = "1,2,3".Split(",").Select(foo.Convert).ToArray();
This way the calling method can be the one who knows how the array is arranged rather than baking it into Convert as a CSV:
int[] bars = "1-2-3".Split("-").Select(foo.Convert).ToArray();
I do wonder what you really gain over swapping foo.Convert out for int.Parse though.. Looks like you're writing a large, confusing, slow mega parser for little gain over offering a static Parse method per your custom type and calling it as per above
I wrote a method in C# which returns Type and based on this type (which is int or long)
private Type GetNumberColumnType(INumberedEntity entity)
{
var numberRow = SG.Framework.Numbering.NumberingService.NumberableEntities.Where(ne => ne.GetType().FullName == entity.ToString()).FirstOrDefault();
var row = (DataRow)numberRow;
return row.Table.Columns[numberRow.NumberColumnName].DataType;
}
I want to get:
GetNumberColumnType(INumberedEntity entity).MaxValue
instead of:
if( GetNumberColumnType(entity) == typeof(long))
long.MaxValue
else
int.MaxValue
What should I do?
If you don't mind using reflection, here's how you go.
var type = GetNumberColumnType(entity);
FieldInfo fi = type.GetField("MaxValue");
if(fi!=null && fi.IsLiteral && !fi.IsInitOnly)
{
object value = fi.GetRawConstantValue();
}
As noted in comments, reflection is expensive, since these are just constants you can just make a lookup
internal class MaxValueCache
{
private static readonly Dictionary<Type, object> maxValues = new Dictionary<Type, object>()
{
{ typeof(int), int.MaxValue},
{ typeof(long), long.MaxValue}
//...
};
public static object GetMaxValue(Type type)
{
return maxValues[type];
}
}
Then use
var type = GetNumberColumnType(entity);
object value = MaxValueCache.GetMaxValue(type);
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...
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();