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);
}
Related
Trying to write a utilty method which determines whether a type is parseable (i.e. has a method like: Parse(string value)
The code below works, but seems a bit kludgey:
public static bool IsParseable(Type t) {
string s = "foo";
Type[] typeArray = { s.GetType() };
if (t.GetRuntimeMethod("Parse", typeArray )==null) {
return false;
} else {
return true;
}
}
It seems like there should be a better way to get my hands on String type then having to create an instance of the type (string) in order to call GetType()
This likewise comes up trying to use the method, as in:
bool results = IsParseable(Double); //doesn't compile.
Instead to find out if double is parseable, I have to do something like.
Double v = 1.0;
Type doubleType = v.GetType();
bool result = IsParseable(doubleType);
Is there a more efficient way? Ultimately I want to use this with generic types, where I have a type parameter T and I want to find out if T has a Parse(String value) method:
IsParseable(T)
which of course doesn't work either. And creating an instance of T isn't a great solution because not known if T has a default constructor.
You can use generic approach
public static bool IsParseable<T>()
{
var argumentTypes = new[] { typeof(string) };
var type = typeof(T);
return type.GetRuntimeMethod("Parse", argumentTypes) != null;
}
// Use it
if (IsParseable<decimal>())
{
// Parse...
}
Or use your approach with Thomas Weller's hint and make method an extension method for Type (even better from readability point of view (opinion based)).
public static bool IsParseable(this Type type)
{
var argumentTypes = new[] { typeof(string) };
return type.GetRuntimeMethod("Parse", argumentTypes) != null;
}
Then use
if (typeof(decimal).IsParseable())
{
// Do something
}
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);
}
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);
}
At the run-time I get boxed instance of some type. How to unbox it to underlying type?
Object obj;
String variable = "Some text";
obj = variable // boxing;
// explicit unboxing, because we know the type of variable at compile time.
var x = (String)obj
// Now let's pretend that we don't know the type of underlying object at compile time.
Type desiredType = obj.GetType(); // But we can figure out.
//And now the question.
//How to express something like this:
var y = (desiredType)obj; //Need to get unboxed instance of initial variable here;
If you don't know the type at compile time, then you can't unbox because you have nowhere to put it - all you can do is store it in an object, which is: boxed.
The same also applies to reference-types like string: you can't cast it to the right type if you don't know the type at compile time: you have nowhere to put it.
You can special-case a few types, for example:
if(obj is int) {
int i = (int)obj;
...
} ...
Another trick that is sometimes (not often) helpful is to switch into generics; then instead of talking in terms of object you are talking in terms of T. This has... limited use though. The easiest way to do that is via dynamic, for example:
dynamic obj = ...
Foo(obj);
...
Foo<T>(T val) { ... code with T ... }
you can also add special cases to that appreach:
Foo(string val) { ... code with string ...}
Foo(int val) { ... code with int ...}
However, frankly I suggest it may be better to look hard at what you are trying to do.
Now lets suppose, that real boxing occur:
int v = 5;
object o = v; //boxed
Type type = o.GetType(); //will return typeof(int)
int convertedBack = (int)Convert.ChangeType(o, type);
Console.WriteLine (convertedBack); //prints 5
Remark, if you substitute:
object convertedBack = Convert.ChangeType(o, type);
Console.WriteLine (convertedBack); //it still prints 5
Console.WriteLine (o); //it even print 5 here
The reason is that underlying object is still int. I've just used this example to show you, that boxing is irrelevant here. You need to rely on some abstraction in your operations and if you want to cast to int dynamically, what reference type do you wan to use.
In such cases I'm going to use the strategy pattern by using a Dictionary<Type, Action<object>>:
internal class Program
{
private static void Main(string[] args)
{
var something = new Something();
something.ComputeValue(13);
something.ComputeValue(DateTime.Now);
something.ComputeValue(DayOfWeek.Monday);
Console.ReadKey();
}
}
internal class Something
{
private static Dictionary<Type, Action<object>> _Strategies;
static Something()
{
// Prepare all available strategies.
_Strategies = new Dictionary<Type, Action<object>>();
_Strategies.Add(typeof(int), ComputeInteger);
_Strategies.Add(typeof(DateTime), ComputeDateTime);
}
public void ComputeValue(object value)
{
Action<object> action;
// Check if we have a matching strategy.
if (!_Strategies.TryGetValue(value.GetType(), out action))
{
// If not, log error, throw exception, whatever.
action = LogUnknownType;
}
// Perform the matching strategy on the given value.
action(value);
}
private static void ComputeDateTime(object source)
{
// We get an object, but we are sure that it will always be an DateTime.
var value = (DateTime)source;
Console.WriteLine("We've got an date time: " + value);
}
private static void ComputeInteger(object source)
{
// We get an object, but we are sure that it will always be an int.
var value = (int)source;
Console.WriteLine("We've got an integer: " + value);
}
private static void LogUnknownType(object source)
{
// What should we do with the drunken sailor?
var unknownType = source.GetType();
Console.WriteLine("Don't know how to handle " + unknownType.FullName);
}
}
Here's an example of exactly why you would do this:
class MyClass
{
public int Id {get;set;}
public string Name {get;set;}
public decimal Val {get;set;}
}
int i = 0;
var myClassImp = new MyClass();
foreach (var val in new [object]{"10", "My name", "100.21"} // Could be read from some data source, such as an excel spreadsheet
{
var prop = typeof(MyClass).GetProperties().ElementAt(i++);
// !!!!!! THROWS EXCEPTION !!!!!!!
prop.SetValue(myClassImp, System.Convert.ChangeType(val, prop.PropertyType), null);
}
The reason for this is because the value is a boxed object... at runtime you do not know the type, so you would have to unbox to the prop.PropertyType
A pragmatic solution; try and use a TypeConverter directly, and if that fails, convert to string and back again:-
private static T GetValueOfType<T>(this ManagementBaseObject MBO, String FieldName) {
T lResult;
try {
Object lObj = MBO[FieldName];
var lSrcType = lObj.GetType();
var lDestType = typeof(T);
if (lDestType.IsValueType && lDestType.IsAssignableFrom(lSrcType)) {
lResult = (T)lObj;
return lResult;
}
var lDestTC = TypeDescriptor.GetConverter(typeof(T));
if (lDestTC.CanConvertFrom(lSrcType)) {
lResult = (T)lDestTC.ConvertFrom(lObj);
} else {
var lSrcTC = TypeDescriptor.GetConverter(lSrcType);
String lTmp = lSrcTC.ConvertToInvariantString(lObj);
lResult = (T)lDestTC.ConvertFromInvariantString(lTmp);
}
} catch {
lResult = default(T);
}
return lResult;
}
Use expressions:
var y = DynamicCast(obj, desiredType);
static object DynamicCast(object source, Type type)
{
var parameter = Expression.Parameter(typeof(object), "input");
var cast = Expression.TypeAs(Expression.Convert(parameter, type), typeof(object));
var lambda = Expression.Lambda<Func<object, object>>(cast, parameter);
var func = lambda.Compile();
return func(source);
}
public static string GetType(object data)
{
Type type = data.GetType();
return Convert.ChangeType(data, type).GetType().Name;
}
Hi,this method receives object data and returns string type name of object.
Hope this is what you need.
you can try using the dynamic runtime
[Test]
public void Test_UnboxingAtRuntime()
{
object boxed = "Hello";
//this line is commented out as it does not compile
// OverloadedMethod(boxed);
var result = CallCorrectMethod(boxed);
Assert.That(result, Is.EqualTo("string"));
boxed = 1;
result = CallCorrectMethod(boxed);
Assert.That(result, Is.EqualTo("int"));
}
public string CallCorrectMethod(dynamic t)
{
return OverloadedMethod(t);
}
public string OverloadedMethod(string s)
{
return "string";
}
public string OverloadedMethod(int s)
{
return "int";
}
I'm trying to serialize a Type object in the following way:
Type myType = typeof (StringBuilder);
var serializer = new XmlSerializer(typeof(Type));
TextWriter writer = new StringWriter();
serializer.Serialize(writer, myType);
When I do this, the call to Serialize throws the following exception:
"The type System.Text.StringBuilder was not expected. Use the
XmlInclude or SoapInclude attribute to specify types that are not
known statically."
Is there a way for me to serialize the Type object? Note that I am not trying to serialize the StringBuilder itself, but the Type object containing the metadata about the StringBuilder class.
I wasn't aware that a Type object could be created with only a string containing the fully-qualified name. To get the fully qualified name, you can use the following:
string typeName = typeof (StringBuilder).FullName;
You can then persist this string however needed, then reconstruct the type like this:
Type t = Type.GetType(typeName);
If you need to create an instance of the type, you can do this:
object o = Activator.CreateInstance(t);
If you check the value of o.GetType(), it will be StringBuilder, just as you would expect.
I had the same problem, and my solution was to create a SerializableType class. It freely converts to and from System.Type, but it serializes as a string. All you have to do is declare the variable as a SerializableType, and from then on you can refer to it as System.Type.
Here is the class:
// a version of System.Type that can be serialized
[DataContract]
public class SerializableType
{
public Type type;
// when serializing, store as a string
[DataMember]
string TypeString
{
get
{
if (type == null)
return null;
return type.FullName;
}
set
{
if (value == null)
type = null;
else
{
type = Type.GetType(value);
}
}
}
// constructors
public SerializableType()
{
type = null;
}
public SerializableType(Type t)
{
type = t;
}
// allow SerializableType to implicitly be converted to and from System.Type
static public implicit operator Type(SerializableType stype)
{
return stype.type;
}
static public implicit operator SerializableType(Type t)
{
return new SerializableType(t);
}
// overload the == and != operators
public static bool operator ==(SerializableType a, SerializableType b)
{
// If both are null, or both are same instance, return true.
if (System.Object.ReferenceEquals(a, b))
{
return true;
}
// If one is null, but not both, return false.
if (((object)a == null) || ((object)b == null))
{
return false;
}
// Return true if the fields match:
return a.type == b.type;
}
public static bool operator !=(SerializableType a, SerializableType b)
{
return !(a == b);
}
// we don't need to overload operators between SerializableType and System.Type because we already enabled them to implicitly convert
public override int GetHashCode()
{
return type.GetHashCode();
}
// overload the .Equals method
public override bool Equals(System.Object obj)
{
// If parameter is null return false.
if (obj == null)
{
return false;
}
// If parameter cannot be cast to SerializableType return false.
SerializableType p = obj as SerializableType;
if ((System.Object)p == null)
{
return false;
}
// Return true if the fields match:
return (type == p.type);
}
public bool Equals(SerializableType p)
{
// If parameter is null return false:
if ((object)p == null)
{
return false;
}
// Return true if the fields match:
return (type == p.type);
}
}
and an example of usage:
[DataContract]
public class A
{
...
[DataMember]
private Dictionary<SerializableType, B> _bees;
...
public B GetB(Type type)
{
return _bees[type];
}
...
}
You might also consider using AssemblyQualifiedName instead of Type.FullName - see comment by #GreyCloud
Brian's answer works well if the type is in the same assembly as the call (like GreyCloud pointed out in one of the comments).
So if the type is in another assembly you need to use the AssemblyQualifiedName as GreyCloud also pointed out.
However as the AssemblyQualifiedName saves the version, if your assemblies have a different version than the one in the string where you have the type, it won't work.
In my case this was an issue and I solved it like this:
string typeName = typeof (MyClass).FullName;
Type type = GetTypeFrom(typeName);
object myInstance = Activator.CreateInstance(type);
GetTypeFrom Method
private Type GetTypeFrom(string valueType)
{
var type = Type.GetType(valueType);
if (type != null)
return type;
try
{
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
//To speed things up, we check first in the already loaded assemblies.
foreach (var assembly in assemblies)
{
type = assembly.GetType(valueType);
if (type != null)
break;
}
if (type != null)
return type;
var loadedAssemblies = assemblies.ToList();
foreach (var loadedAssembly in assemblies)
{
foreach (AssemblyName referencedAssemblyName in loadedAssembly.GetReferencedAssemblies())
{
var found = loadedAssemblies.All(x => x.GetName() != referencedAssemblyName);
if (!found)
{
try
{
var referencedAssembly = Assembly.Load(referencedAssemblyName);
type = referencedAssembly.GetType(valueType);
if (type != null)
break;
loadedAssemblies.Add(referencedAssembly);
}
catch
{
//We will ignore this, because the Type might still be in one of the other Assemblies.
}
}
}
}
}
catch(Exception exception)
{
//throw my custom exception
}
if (type == null)
{
//throw my custom exception.
}
return type;
}
I am posting this in case anyone needs it.
According to the MSDN documentation of System.Type [1] you should be able to serialize the System.Type object. However, as the error is explicitly referring to System.Text.StringBuilder, that is likely the class that is causing the serialization error.
[1] Type Class (System) - http://msdn.microsoft.com/en-us/library/system.type.aspx
I came across this issue trying to do binary serialization in .net standard 2.0. I ended up solving the problem using a custom SurrogateSelector and SerializationBinder.
The TypeSerializationBinder was required because the framework was having trouble resolving System.RuntimeType before it got SurrogateSelector. I don't really understand why the type must be resolved before this step though...
Here is the code:
// Serializes and deserializes System.Type
public class TypeSerializationSurrogate : ISerializationSurrogate {
public void GetObjectData(object obj, SerializationInfo info, StreamingContext context) {
info.AddValue(nameof(Type.FullName), (obj as Type).FullName);
}
public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector) {
return Type.GetType(info.GetString(nameof(Type.FullName)));
}
}
// Just a stub, doesn't need an implementation
public class TypeStub : Type { ... }
// Binds "System.RuntimeType" to our TypeStub
public class TypeSerializationBinder : SerializationBinder {
public override Type BindToType(string assemblyName, string typeName) {
if(typeName == "System.RuntimeType") {
return typeof(TypeStub);
}
return Type.GetType($"{typeName}, {assemblyName}");
}
}
// Selected out TypeSerializationSurrogate when [de]serializing Type
public class TypeSurrogateSelector : ISurrogateSelector {
public virtual void ChainSelector(ISurrogateSelector selector) => throw new NotSupportedException();
public virtual ISurrogateSelector GetNextSelector() => throw new NotSupportedException();
public virtual ISerializationSurrogate GetSurrogate(Type type, StreamingContext context, out ISurrogateSelector selector) {
if(typeof(Type).IsAssignableFrom(type)) {
selector = this;
return new TypeSerializationSurrogate();
}
selector = null;
return null;
}
}
Usage Example:
byte[] bytes
var serializeFormatter = new BinaryFormatter() {
SurrogateSelector = new TypeSurrogateSelector()
}
using (var stream = new MemoryStream()) {
serializeFormatter.Serialize(stream, typeof(string));
bytes = stream.ToArray();
}
var deserializeFormatter = new BinaryFormatter() {
SurrogateSelector = new TypeSurrogateSelector(),
Binder = new TypeDeserializationBinder()
}
using (var stream = new MemoryStream(bytes)) {
type = (Type)deserializeFormatter .Deserialize(stream);
Assert.Equal(typeof(string), type);
}
Just looked at its definition, it is not marked as Serializable. If you really need this data to be serialize, then you may have to convert it to a custom class that is marked as such.
public abstract class Type : System.Reflection.MemberInfo
Member of System
Summary:
Represents type declarations: class types, interface types, array types, value types, enumeration types, type parameters, generic type definitions, and open or closed constructed generic types.
Attributes:
[System.Runtime.InteropServices.ClassInterfaceAttribute(0),
System.Runtime.InteropServices.ComDefaultInterfaceAttribute(System.Runtime.InteropServices._Type),
System.Runtime.InteropServices.ComVisibleAttribute(true)]