How do i use Activator.CreateInstance with strings? - c#

In my reflection code i hit a problem with my generic section of code. Specifically when i use a string.
var oVal = (object)"Test";
var oType = oVal.GetType();
var sz = Activator.CreateInstance(oType, oVal);
Exception
An unhandled exception of type 'System.MissingMethodException' occurred in mscorlib.dll
Additional information: Constructor on type 'System.String' not found.
I tried this for testing purposes and it occurs in this single liner too
var sz = Activator.CreateInstance("".GetType(), "Test");
originally i wrote
var sz = Activator.CreateInstance("".GetType());
but i get this error
Additional information: No parameterless constructor defined for this object.
How do i create a string using reflection?

Keep in mind that the string class is immutable. It cannot be changed after it is created. That explains why it doesn't have a parameterless constructor, it could never generate a useful string object other than an empty string. That's already available in the C# language, it is "".
Same reasoning applies for a string(String) constructor. There is no point in duplicating a string, the string you'd pass to the constructor is already a perfectly good instance of the string.
So fix your problem by testing for the string case:
var oType = oVal.GetType();
if (oType == typeof(string)) return oVal as string;
else return Activator.CreateInstance(oType, oVal);

You are trying to do this :
var sz = new string();
Try to compile it, you will understand your error.
You may try :
var sz = Activator.CreateInstance(typeof(string), new object[] {"value".ToCharArray()});
But it looks useless, you should directly use value...

It looks like you're trying to call a constructor which just takes a string - and there isn't such a constructor. If you've already got a string, why are you trying to create a new one? (When you didn't provide any further arguments, you were trying to call a parameterless constructor - which again, doesn't exist.)
Note that typeof(string) is a simpler way to get a reference to the string type.
Could you give us more information about the bigger picture of what you're trying to do?

String actually has no constructor that takes a string as input. There is a constructor that takes a char array so this should work:
var sz = Activator.CreateInstance ("".GetType (), "Test".ToCharArray ());

This is what I use in my projects. As far as needing to create an instantiation of a type of object and not knowing at design time, is rather normal for me. Perhaps you are cycling through object properties and you want to instantiate all of them dynamically. I have many times needed to create then assign values to non instantiated POCO objects... with the below code you can use a string value stored in the DB to instantiate an object as well or instantiate an object stored in a library that is referencing your library - so you can bypass circular reference errors as well... Hope it helps.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
/// <summary>
/// Instantiates an object. Must pass PropertyType.AssemblyQualifiedName for factory to operate
/// returns instantiated object
/// </summary>
/// <param name="typeName"></param>
/// <returns></returns>
public static object Create(string typeAssemblyQualifiedName)
{
// resolve the type
Type targetType = ResolveType(typeAssemblyQualifiedName);
if (targetType == null)
throw new ArgumentException("Unable to resolve object type: " + typeAssemblyQualifiedName);
return Create(targetType);
}
/// <summary>
/// create by type of T
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static T Create<T>()
{
Type targetType = typeof(T);
return (T)Create(targetType);
}
/// <summary>
/// general object creation
/// </summary>
/// <param name="targetType"></param>
/// <returns></returns>
public static object Create(Type targetType)
{
//string test first - it has no parameterless constructor
if (Type.GetTypeCode(targetType) == TypeCode.String)
return string.Empty;
// get the default constructor and instantiate
Type[] types = new Type[0];
ConstructorInfo info = targetType.GetConstructor(types);
object targetObject = null;
if (info == null) //must not have found the constructor
if (targetType.BaseType.UnderlyingSystemType.FullName.Contains("Enum"))
targetObject = Activator.CreateInstance(targetType);
else
throw new ArgumentException("Unable to instantiate type: " + targetType.AssemblyQualifiedName + " - Constructor not found");
else
targetObject = info.Invoke(null);
if (targetObject == null)
throw new ArgumentException("Unable to instantiate type: " + targetType.AssemblyQualifiedName + " - Unknown Error");
return targetObject;
}
/// <summary>
/// Loads the assembly of an object. Must pass PropertyType.AssemblyQualifiedName for factory to operate
/// Returns the object type.
/// </summary>
/// <param name="typeString"></param>
/// <returns></returns>
public static Type ResolveType(string typeAssemblyQualifiedName)
{
int commaIndex = typeAssemblyQualifiedName.IndexOf(",");
string className = typeAssemblyQualifiedName.Substring(0, commaIndex).Trim();
string assemblyName = typeAssemblyQualifiedName.Substring(commaIndex + 1).Trim();
if (className.Contains("[]"))
className.Remove(className.IndexOf("[]"), 2);
// Get the assembly containing the handler
Assembly assembly = null;
try
{
assembly = Assembly.Load(assemblyName);
}
catch
{
try
{
assembly = Assembly.LoadWithPartialName(assemblyName);//yes yes this is obsolete but it is only a backup call
}
catch
{
throw new ArgumentException("Can't load assembly " + assemblyName);
}
}
// Get the handler
return assembly.GetType(className, false, false);
}

Related

Get type of object parameter in generic method [duplicate]

I have a method with an out parameter that tries to do a type conversion. Basically:
public void GetParameterValue(out object destination)
{
object paramVal = "I want to return this. could be any type, not just string.";
destination = null; // default out param to null
destination = Convert.ChangeType(paramVal, destination.GetType());
}
The problem is that usually someone would call this like:
string output;
GetParameterValue(output);
This will fail because of:
destination.GetType()
destination is null, so we can't call .GetType() on it. We also can not call:
typeof(destination)
because destination is a variable name not a type name.
So is there any way to get the type of an object that is set to null? I would think there would have to be a way to know what type a storage location is without it being assigned anything.
Just to give a bit more info, I am trying to make a utility method that will grab the output parameters of an Oracle stored procedure. The issue is that DbParameter.Value is of type object.
What would be ideal would be for the developers to do something like:
string val = GetParameterValue("parameterName");
The notable thing is that there is no casting of types. In practice, you don't know the lparam of the "equals", so I went with:
string val;
GetParameterValue("parameterName", out val);
And figured within the method, I would know the destination type of the output variable. I guess that was a bad assumption. As an alternative, I also wrote the method:
public T GetParameterValue<T>(string paramName)
So the developers can do:
string val = GetParameterValue<string>("parameterName");
I find the explicit "string" declaration to be repetitive, especially since in practice, the destination if probably an object property and the oracle data type could change (think ORM):
MyObj.SomeProp = GetParameterValue<MyObj.SomeProp.GetType()>("parameterName");
But again, if MyObj.SomeProp is null, that .GetType() call fails. The VM has to know the type of MyObj.SomeProp, even when its null, right? or else how would it catch cast exceptions?
To partially solve my own problem, I can do:
MyObj.SomeProp = GetParameterValue<typeof(MyObj).GetField("SomeProp").GetType()>("parameterName");
The whole idea was to not have to explicitly use the Type in more than one place, so that if the data type changes, it only has to be changed in the destination object (MyObj.SomeProp) and in the DB. There has to be a better way...
So is there any way to get the type of an object that is set to null? I would think there would have to be a way to know what type a storage location is without it being assigned anything.
Not necessarily. The best that you can say is that it is an object. A null reference does not point to any storage location, so there is no metadata from which it can make that determination.
The best that you could do is change it to be more generic, as in:
public void GetParameterValue<T>(out T destination)
{
object paramVal = "Blah";
destination = default(T);
destination = Convert.ChangeType(paramVal, typeof(T));
}
The type of T can be inferred, so you shouldn't need to give a type parameter to the method explicitly.
It's possible if you don't mind declaring your method as a generic. Try this.
class Program
{
public static void GetParameterValue<T>(out T destination)
{
Console.WriteLine("typeof(T)=" + typeof(T).Name);
destination = default(T);
}
static void Main(string[] args)
{
string s;
GetParameterValue(out s);
int i;
GetParameterValue(out i);
}
}
The following extension method returns the type of its parameter as it was declared, regardless of its contents:
using System;
namespace MyNamespace
{
public static class Extensions
{
/// <summary>
/// Gets the declared type of the specified object.
/// </summary>
/// <typeparam name="T">The type of the object.</typeparam>
/// <param name="obj">The object.</param>
/// <returns>
/// A <see cref="Type"/> object representing type
/// <typeparamref name="T"/>; i.e., the type of <paramref name="obj"/>
/// as it was declared. Note that the contents of
/// <paramref name="obj"/> are irrelevant; if <paramref name="obj"/>
/// contains an object whose class is derived from
/// <typeparamref name="T"/>, then <typeparamref name="T"/> is
/// returned, not the derived type.
/// </returns>
public static Type GetDeclaredType<T>(
this T obj )
{
return typeof( T );
}
}
}
Since this is an extension method, its argument can be a null reference, and all of the following works OK:
string myString = "abc";
object myObj = myString;
Type myObjType = myObj.GetDeclaredType();
string myNullString = null;
object myNullObj = myNullString;
Type myNullObjType = myNullObj.GetDeclaredType();
Note that myObjType and myNullObjType will both be set to System.Object, not System.String.
If you actually want the type of obj's contents when it's not null, then change the return line to:
return (obj != null) ? obj.GetType() : typeof( T );
Currently, you have no way of knowing what gets passed into the method. You can convert it into a generic method like this:
public void GetParameterValue<T>(out T destination)
{
...
}
The type of your destination variable is always System.Object. You could just return
Convert.ChangeType(paramVal, System.Object).
#Rally25s:
string val;
GetParameterValue("parameterName", out val);
It's unclear from your message (in the answers) what the problem with that one was. If declared as:
void GetParameterValue<T>(string parameterName, out T val) { }
Than the call, as you wrote it above, will work (you don't need to specify the type). I'm guess that didn't work for you because you can't use a property as an "out" parameter. The way around that is to use both methods:
T GetParameterValue<T>(string parameterName, T ununsed) { }
This would be called like this:
MyObj.SomeProp = GetParameterValue("parameterName", MyObj.SomeProp);
which is rather kludgey, but not the worse method presented.
A different method, which I've used in C++, but haven't tried yet in C#, is to have GetParameterValue() some object of you own design, and then implement a number of implicit cast operators for it.
class ParameterHelper
{
private object value;
public ParameterHelper(object value) { this.value = value; }
public static implicit operator int(ParameterHelper v)
{ return (int) v.value; }
}
ParameterHelper GetParameterValue( string parameterName);
MyObj.SomeProp = GetParameterValue("parameterName");
I don't think it is possible to get the type when the value is null. Also, since you are calling inside GetParameterValue, the best you could do (when the value is null) is to get the type of the "destination" parameter which is "object". You might consider passing the Type as a parameter to GetParameterValue where you have more information, such as:
public void GetParameterValue(Type sourceType, out object destination) { //... }
If there is no instance, there is no instance type.
The best you can do is use the type of the reference, which means if you have an object reference (as in the method in the question), the reference type is object.
You probably shouldn't be trying to convert a null instance of one type into a null instance of another type...
In your example it would be null of type System.Object.
Does your example even compile? I get a "cannot convert from 'out string' to 'out object'" error.
At a theoretical level isn't a null really the same as a void pointer in C, which is to say that it holds a memory address and that's it? If so then it is similar to the case of a division by zero in Mathematics where the result is undefined.
One could do the following for this line:
string val = GetParameterValue<string>("parameterName");
Just remove that first string and now there isn't the repetition:
var val = GetParameterValue<string>("parameterName");
Not necessarily what you are looking for, though there is the question of how does one interpret null?
//**The working answer**
//**based on your discussion eheheheheeh**
public void s<T>(out T varName)
{
if (typeof (T) == typeof(HtmlTable))
{
//////////
}
}
protected void Page_Load(object sender, EventArgs e)
{
HtmlTable obj=null ;
s(out obj);
}
http://msdn.microsoft.com/en-us/library/58918ffs.aspx
or
private Hashtable propertyTable = new Hashtable();
public void LoadPropertyTypes()
{
Type t = this.GetType();
System.Reflection.MemberInfo[] memberInfo = t.GetMembers();
foreach (System.Reflection.MemberInfo mInfo in memberInfo)
{
string[] prop = mInfo.ToString().Split(Convert.ToChar(" "));
propertyTable.Add(prop[1], prop[0]);
}
}
public string GetMemberType(string propName)
{
if (propertyTable.ContainsKey(propName))
{
return Convert.ToString(propertyTable[propName]);
}
else{
return "N/A";
}
}
in that way we can use switch to manage different property types.

How to get class reference from string? [duplicate]

I have a list of types (System.Type) which need te be queried on the database.
For each of this types, I need to call the following extensionmethod (which is part of LinqToNhibernate):
Session.Linq<MyType>()
However I do not have MyType, but I want to use a Type instead.
What I have is:
System.Type typeOne;
But I cannot perform the following:
Session.Linq<typeOne>()
How can I use a Type as a Generic parameter?
You can't, directly. The point of generics is to provide compile-time type safety, where you know the type you're interested in at compile-time, and can work with instances of that type. In your case, you only know the Type so you can't get any compile-time checks that any objects you have are instances of that type.
You'll need to call the method via reflection - something like this:
// Get the generic type definition
MethodInfo method = typeof(Session).GetMethod("Linq",
BindingFlags.Public | BindingFlags.Static);
// Build a method with the specific type argument you're interested in
method = method.MakeGenericMethod(typeOne);
// The "null" is because it's a static method
method.Invoke(null, arguments);
If you need to use this type a lot, you might find it more convenient to write your own generic method which calls whatever other generic methods it needs, and then call your method with reflection.
To do this you need to use reflection:
typeof(Session).GetMethod("Linq").MakeGenericMethod(typeOne).Invoke(null, null);
(assuming that Linq<T>() is a static method on the type Session)
If Session is actually an object, you'll need to know where the Linq method is actually declared, and pass in Session as an argument:
typeof(DeclaringType).GetMethod("Linq").MakeGenericMethod(typeOne)
.Invoke(null, new object[] {Session});
I have one general method which call Call Generic Method Through Reflection
/// <summary>
/// This method call your method through Reflection
/// so i wil call the method like CallGenericMethodThroughReflection<Session>(assemblyQualifiedName,Linq,false,new[] { file })
/// </summary>
/// <typeparam name="T">Call method from which file</typeparam>
/// <param name="assemblyQualifiedName">Your can get assemblyQualifiedName like typeof(Payroll.Domain.Attendance.AttendanceApplicationMaster).AssemblyQualifiedName</param>
/// <param name="methodName"></param>
/// <param name="isStaticMethod"></param>
/// <param name="paramaterList"></param>
/// <param name="parameterType">pass parameter type list in case of the given method have overload </param>
/// <returns>return object of calling method</returns>
public static object CallGenericMethodThroughReflection<T>(string assemblyQualifiedName, string methodName,bool isStaticMethod ,object[] paramaterList,Type[] parameterType = null)
{
try
{
object instance = null;
var bindingAttr = BindingFlags.Static | BindingFlags.Public;
if (!isStaticMethod)
{
instance = Activator.CreateInstance<T>();
bindingAttr = BindingFlags.Instance | BindingFlags.Public;
}
MethodInfo MI = null;
var type = Type.GetType(assemblyQualifiedName);
if(parameterType == null)
MI = typeof(T).GetMethod(methodName, bindingAttr);
else
MI = typeof(T).GetMethod(methodName, bindingAttr,null, parameterType, null);//this will work in most case some case not work
if (type == null || MI == null) // if the condition is true it means given method or AssemblyQualifiedName entity not found
return null;
var genericMethod = MI.MakeGenericMethod(new[] { type });
return genericMethod.Invoke(instance, paramaterList);
}
catch (Exception ex)
{
throw ex;
}
}

How to get the Type of an object that is a Nullable<Int> when the value is null [duplicate]

I have a method with an out parameter that tries to do a type conversion. Basically:
public void GetParameterValue(out object destination)
{
object paramVal = "I want to return this. could be any type, not just string.";
destination = null; // default out param to null
destination = Convert.ChangeType(paramVal, destination.GetType());
}
The problem is that usually someone would call this like:
string output;
GetParameterValue(output);
This will fail because of:
destination.GetType()
destination is null, so we can't call .GetType() on it. We also can not call:
typeof(destination)
because destination is a variable name not a type name.
So is there any way to get the type of an object that is set to null? I would think there would have to be a way to know what type a storage location is without it being assigned anything.
Just to give a bit more info, I am trying to make a utility method that will grab the output parameters of an Oracle stored procedure. The issue is that DbParameter.Value is of type object.
What would be ideal would be for the developers to do something like:
string val = GetParameterValue("parameterName");
The notable thing is that there is no casting of types. In practice, you don't know the lparam of the "equals", so I went with:
string val;
GetParameterValue("parameterName", out val);
And figured within the method, I would know the destination type of the output variable. I guess that was a bad assumption. As an alternative, I also wrote the method:
public T GetParameterValue<T>(string paramName)
So the developers can do:
string val = GetParameterValue<string>("parameterName");
I find the explicit "string" declaration to be repetitive, especially since in practice, the destination if probably an object property and the oracle data type could change (think ORM):
MyObj.SomeProp = GetParameterValue<MyObj.SomeProp.GetType()>("parameterName");
But again, if MyObj.SomeProp is null, that .GetType() call fails. The VM has to know the type of MyObj.SomeProp, even when its null, right? or else how would it catch cast exceptions?
To partially solve my own problem, I can do:
MyObj.SomeProp = GetParameterValue<typeof(MyObj).GetField("SomeProp").GetType()>("parameterName");
The whole idea was to not have to explicitly use the Type in more than one place, so that if the data type changes, it only has to be changed in the destination object (MyObj.SomeProp) and in the DB. There has to be a better way...
So is there any way to get the type of an object that is set to null? I would think there would have to be a way to know what type a storage location is without it being assigned anything.
Not necessarily. The best that you can say is that it is an object. A null reference does not point to any storage location, so there is no metadata from which it can make that determination.
The best that you could do is change it to be more generic, as in:
public void GetParameterValue<T>(out T destination)
{
object paramVal = "Blah";
destination = default(T);
destination = Convert.ChangeType(paramVal, typeof(T));
}
The type of T can be inferred, so you shouldn't need to give a type parameter to the method explicitly.
It's possible if you don't mind declaring your method as a generic. Try this.
class Program
{
public static void GetParameterValue<T>(out T destination)
{
Console.WriteLine("typeof(T)=" + typeof(T).Name);
destination = default(T);
}
static void Main(string[] args)
{
string s;
GetParameterValue(out s);
int i;
GetParameterValue(out i);
}
}
The following extension method returns the type of its parameter as it was declared, regardless of its contents:
using System;
namespace MyNamespace
{
public static class Extensions
{
/// <summary>
/// Gets the declared type of the specified object.
/// </summary>
/// <typeparam name="T">The type of the object.</typeparam>
/// <param name="obj">The object.</param>
/// <returns>
/// A <see cref="Type"/> object representing type
/// <typeparamref name="T"/>; i.e., the type of <paramref name="obj"/>
/// as it was declared. Note that the contents of
/// <paramref name="obj"/> are irrelevant; if <paramref name="obj"/>
/// contains an object whose class is derived from
/// <typeparamref name="T"/>, then <typeparamref name="T"/> is
/// returned, not the derived type.
/// </returns>
public static Type GetDeclaredType<T>(
this T obj )
{
return typeof( T );
}
}
}
Since this is an extension method, its argument can be a null reference, and all of the following works OK:
string myString = "abc";
object myObj = myString;
Type myObjType = myObj.GetDeclaredType();
string myNullString = null;
object myNullObj = myNullString;
Type myNullObjType = myNullObj.GetDeclaredType();
Note that myObjType and myNullObjType will both be set to System.Object, not System.String.
If you actually want the type of obj's contents when it's not null, then change the return line to:
return (obj != null) ? obj.GetType() : typeof( T );
Currently, you have no way of knowing what gets passed into the method. You can convert it into a generic method like this:
public void GetParameterValue<T>(out T destination)
{
...
}
The type of your destination variable is always System.Object. You could just return
Convert.ChangeType(paramVal, System.Object).
#Rally25s:
string val;
GetParameterValue("parameterName", out val);
It's unclear from your message (in the answers) what the problem with that one was. If declared as:
void GetParameterValue<T>(string parameterName, out T val) { }
Than the call, as you wrote it above, will work (you don't need to specify the type). I'm guess that didn't work for you because you can't use a property as an "out" parameter. The way around that is to use both methods:
T GetParameterValue<T>(string parameterName, T ununsed) { }
This would be called like this:
MyObj.SomeProp = GetParameterValue("parameterName", MyObj.SomeProp);
which is rather kludgey, but not the worse method presented.
A different method, which I've used in C++, but haven't tried yet in C#, is to have GetParameterValue() some object of you own design, and then implement a number of implicit cast operators for it.
class ParameterHelper
{
private object value;
public ParameterHelper(object value) { this.value = value; }
public static implicit operator int(ParameterHelper v)
{ return (int) v.value; }
}
ParameterHelper GetParameterValue( string parameterName);
MyObj.SomeProp = GetParameterValue("parameterName");
I don't think it is possible to get the type when the value is null. Also, since you are calling inside GetParameterValue, the best you could do (when the value is null) is to get the type of the "destination" parameter which is "object". You might consider passing the Type as a parameter to GetParameterValue where you have more information, such as:
public void GetParameterValue(Type sourceType, out object destination) { //... }
If there is no instance, there is no instance type.
The best you can do is use the type of the reference, which means if you have an object reference (as in the method in the question), the reference type is object.
You probably shouldn't be trying to convert a null instance of one type into a null instance of another type...
In your example it would be null of type System.Object.
Does your example even compile? I get a "cannot convert from 'out string' to 'out object'" error.
At a theoretical level isn't a null really the same as a void pointer in C, which is to say that it holds a memory address and that's it? If so then it is similar to the case of a division by zero in Mathematics where the result is undefined.
One could do the following for this line:
string val = GetParameterValue<string>("parameterName");
Just remove that first string and now there isn't the repetition:
var val = GetParameterValue<string>("parameterName");
Not necessarily what you are looking for, though there is the question of how does one interpret null?
//**The working answer**
//**based on your discussion eheheheheeh**
public void s<T>(out T varName)
{
if (typeof (T) == typeof(HtmlTable))
{
//////////
}
}
protected void Page_Load(object sender, EventArgs e)
{
HtmlTable obj=null ;
s(out obj);
}
http://msdn.microsoft.com/en-us/library/58918ffs.aspx
or
private Hashtable propertyTable = new Hashtable();
public void LoadPropertyTypes()
{
Type t = this.GetType();
System.Reflection.MemberInfo[] memberInfo = t.GetMembers();
foreach (System.Reflection.MemberInfo mInfo in memberInfo)
{
string[] prop = mInfo.ToString().Split(Convert.ToChar(" "));
propertyTable.Add(prop[1], prop[0]);
}
}
public string GetMemberType(string propName)
{
if (propertyTable.ContainsKey(propName))
{
return Convert.ToString(propertyTable[propName]);
}
else{
return "N/A";
}
}
in that way we can use switch to manage different property types.

Default value of a type at Runtime [duplicate]

This question already has answers here:
how to get the default value of a type if the type is only known as System.Type? [duplicate]
(3 answers)
Closed 9 years ago.
For any given type i want to know its default value.
In C#, there is a keyword called default for doing this like
object obj = default(Decimal);
but I have an instance of Type (called myType) and if I say this,
object obj = default(myType);
it doesn't work
Is there any good way of doing this?
I know that a huge switch block will work but thats not a good choice.
There's really only two possibilities: null for reference types and new myType() for value types (which corresponds to 0 for int, float, etc) So you really only need to account for two cases:
object GetDefaultValue(Type t)
{
if (t.IsValueType)
return Activator.CreateInstance(t);
return null;
}
(Because value types always have a default constructor, that call to Activator.CreateInstance will never fail).
You could also add it as an extension method to System.Type:
public static class TypeExtensions
{
public static object GetDefaultValue(this Type t)
{
if (t.IsValueType && Nullable.GetUnderlyingType(t) == null)
return Activator.CreateInstance(t);
else
return null;
}
}
Having solved this problem in my own systems, here is a method for correctly determining the default value of an arbitrary Type at run time, which has been tested against thousands of Types:
/// <summary>
/// [ <c>public static object GetDefault(this Type type)</c> ]
/// <para></para>
/// Retrieves the default value for a given Type
/// </summary>
/// <param name="type">The Type for which to get the default value</param>
/// <returns>The default value for <paramref name="type"/></returns>
/// <remarks>
/// If a null Type, a reference Type, or a System.Void Type is supplied, this method always returns null. If a value type
/// is supplied which is not publicly visible or which contains generic parameters, this method will fail with an
/// exception.
/// </remarks>
/// <example>
/// To use this method in its native, non-extension form, make a call like:
/// <code>
/// object Default = DefaultValue.GetDefault(someType);
/// </code>
/// To use this method in its Type-extension form, make a call like:
/// <code>
/// object Default = someType.GetDefault();
/// </code>
/// </example>
/// <seealso cref="GetDefault<T>"/>
public static object GetDefault(this Type type)
{
// If no Type was supplied, if the Type was a reference type, or if the Type was a System.Void, return null
if (type == null || !type.IsValueType || type == typeof(void))
return null;
// If the supplied Type has generic parameters, its default value cannot be determined
if (type.ContainsGenericParameters)
throw new ArgumentException(
"{" + MethodInfo.GetCurrentMethod() + "} Error:\n\nThe supplied value type <" + type +
"> contains generic parameters, so the default value cannot be retrieved");
// If the Type is a primitive type, or if it is another publicly-visible value type (i.e. struct/enum), return a
// default instance of the value type
if (type.IsPrimitive || !type.IsNotPublic)
{
try
{
return Activator.CreateInstance(type);
}
catch (Exception e)
{
throw new ArgumentException(
"{" + MethodInfo.GetCurrentMethod() + "} Error:\n\nThe Activator.CreateInstance method could not " +
"create a default instance of the supplied value type <" + type +
"> (Inner Exception message: \"" + e.Message + "\")", e);
}
}
// Fail with exception
throw new ArgumentException("{" + MethodInfo.GetCurrentMethod() + "} Error:\n\nThe supplied value type <" + type +
"> is not a publicly-visible type, so the default value cannot be retrieved");
}
In these examples, the GetDefault method is implemented in the static class DefaultValue. Call this method with a statement like:
object Default = DefaultValue.GetDefault(someType);
To use the GetDefault method as an extension method for Type, call it like this:
object Default = someType.GetDefault();
This second, Type-extension approach is a simpler client-code syntax, since it removes the need to reference the containing DefaultValue class qualifier on the call.
The above run time form of GetDefault works with identical semantics as the primitive C# 'default' keyword, and produces the same results.
To use a generic form of GetDefault, you may access the following function:
/// <summary>
/// [ <c>public static T GetDefault< T >()</c> ]
/// <para></para>
/// Retrieves the default value for a given Type
/// </summary>
/// <typeparam name="T">The Type for which to get the default value</typeparam>
/// <returns>The default value for Type T</returns>
/// <remarks>
/// If a reference Type or a System.Void Type is supplied, this method always returns null. If a value type
/// is supplied which is not publicly visible or which contains generic parameters, this method will fail with an
/// exception.
/// </remarks>
/// <seealso cref="GetDefault(Type)"/>
public static T GetDefault<T>()
{
return (T) GetDefault(typeof(T));
}
A call to the generic form could be something like:
int? inDefaultVal = DefaultValue.GetDefault<int?>();
Of course, the above generic form of GetDefault is unnecessary for C#, since it works the same as default(T). It is only useful for a .NET language that does not support the 'default' keyword but which supports generic types. In most cases, the generic form is unnecessary.
A useful corollary method is one to determine whether an object contains the default value for its Type. I also rely on the following IsObjectSetToDefault method for that purpose:
/// <summary>
/// [ <c>public static bool IsObjectSetToDefault(this Type ObjectType, object ObjectValue)</c> ]
/// <para></para>
/// Reports whether a value of type T (or a null reference of type T) contains the default value for that Type
/// </summary>
/// <remarks>
/// Reports whether the object is empty or unitialized for a reference type or nullable value type (i.e. is null) or
/// whether the object contains a default value for a non-nullable value type (i.e. int = 0, bool = false, etc.)
/// <para></para>
/// NOTE: For non-nullable value types, this method introduces a boxing/unboxing performance penalty.
/// </remarks>
/// <param name="ObjectType">Type of the object to test</param>
/// <param name="ObjectValue">The object value to test, or null for a reference Type or nullable value Type</param>
/// <returns>
/// true = The object contains the default value for its Type.
/// <para></para>
/// false = The object has been changed from its default value.
/// </returns>
public static bool IsObjectSetToDefault(this Type ObjectType, object ObjectValue)
{
// If no ObjectType was supplied, attempt to determine from ObjectValue
if (ObjectType == null)
{
// If no ObjectValue was supplied, abort
if (ObjectValue == null)
{
MethodBase currmethod = MethodInfo.GetCurrentMethod();
string ExceptionMsgPrefix = currmethod.DeclaringType + " {" + currmethod + "} Error:\n\n";
throw new ArgumentNullException(ExceptionMsgPrefix + "Cannot determine the ObjectType from a null Value");
}
// Determine ObjectType from ObjectValue
ObjectType = ObjectValue.GetType();
}
// Get the default value of type ObjectType
object Default = ObjectType.GetDefault();
// If a non-null ObjectValue was supplied, compare Value with its default value and return the result
if (ObjectValue != null)
return ObjectValue.Equals(Default);
// Since a null ObjectValue was supplied, report whether its default value is null
return Default == null;
}
The above IsObjectSetToDefault method can either be called in its native form or accessed as a Type-class extension.
How about something like...
class Program
{
static void Main(string[] args)
{
PrintDefault(typeof(object));
PrintDefault(typeof(string));
PrintDefault(typeof(int));
PrintDefault(typeof(int?));
}
private static void PrintDefault(Type type)
{
Console.WriteLine("default({0}) = {1}", type,
DefaultGenerator.GetDefaultValue(type));
}
}
public class DefaultGenerator
{
public static object GetDefaultValue(Type parameter)
{
var defaultGeneratorType =
typeof(DefaultGenerator<>).MakeGenericType(parameter);
return defaultGeneratorType.InvokeMember(
"GetDefault",
BindingFlags.Static |
BindingFlags.Public |
BindingFlags.InvokeMethod,
null, null, new object[0]);
}
}
public class DefaultGenerator<T>
{
public static T GetDefault()
{
return default(T);
}
}
It produces the following output:
default(System.Object) =
default(System.String) =
default(System.Int32) = 0
default(System.Nullable`1[System.Int32]) =
What do you mean by "Default Value"? All reference Types ("class") have null as default value, while all value types will have their default values according to this table.
Here's a function that will return the default value for a nullable type (in other words, it returns 0 for both Decimal and Decimal?):
public static object DefaultValue(Type maybeNullable)
{
Type underlying = Nullable.GetUnderlyingType(maybeNullable);
if (underlying != null)
return Activator.CreateInstance(underlying);
return Activator.CreateInstance(maybeNullable);
}

How to check if an object is serializable in C#

I am looking for an easy way to check if an object in C# is serializable.
As we know you make an object serializable by either implementing the ISerializable interface or by placing the [Serializable] at the top of the class.
What I am looking for is a quick way to check this without having to reflect the class to get it's attributes. The interface would be quick using an is statement.
Using #Flard's suggestion this is the code that I have come up with, scream is there is a better way.
private static bool IsSerializable(T obj)
{
return ((obj is ISerializable) || (Attribute.IsDefined(typeof (T), typeof (SerializableAttribute))));
}
Or even better just get the type of the object and then use the IsSerializable property on the type:
typeof(T).IsSerializable
Remember though this this seems to only just the class that we are dealing with if the class contains other classes you probably want to check them all or try and serialize and wait for errors as #pb pointed out.
You have a lovely property on the Type class called IsSerializable.
You're going to have to check all types in the graph of objects being serialized for the serializable attribute. The easiest way is to try to serialize the object and catch the exception. (But that's not the cleanest solution). Type.IsSerializable and checking for the serializalbe attribute don't take the graph into account.
Sample
[Serializable]
public class A
{
public B B = new B();
}
public class B
{
public string a = "b";
}
[Serializable]
public class C
{
public D D = new D();
}
[Serializable]
public class D
{
public string d = "D";
}
class Program
{
static void Main(string[] args)
{
var a = typeof(A);
var aa = new A();
Console.WriteLine("A: {0}", a.IsSerializable); // true (WRONG!)
var c = typeof(C);
Console.WriteLine("C: {0}", c.IsSerializable); //true
var form = new BinaryFormatter();
// throws
form.Serialize(new MemoryStream(), aa);
}
}
This is an old question, that may need to be updated for .NET 3.5+. Type.IsSerializable can actually return false if the class uses the DataContract attribute. Here is a snippet i use, if it stinks, let me know :)
public static bool IsSerializable(this object obj)
{
Type t = obj.GetType();
return Attribute.IsDefined(t, typeof(DataContractAttribute)) || t.IsSerializable || (obj is IXmlSerializable)
}
Use Type.IsSerializable as others have pointed out.
It's probably not worth attempting to reflect and check if all members in the object graph are serializable.
A member could be declared as a serializable type, but in fact be instantiated as a derived type that is not serializable, as in the following contrived example:
[Serializable]
public class MyClass
{
public Exception TheException; // serializable
}
public class MyNonSerializableException : Exception
{
...
}
...
MyClass myClass = new MyClass();
myClass.TheException = new MyNonSerializableException();
// myClass now has a non-serializable member
Therefore, even if you determine that a specific instance of your type is serializable, you can't in general be sure this will be true of all instances.
Attribute.IsDefined(typeof (YourClass), typeof (SerializableAttribute));
Probably involves reflection underwater, but the most simple way?
Here's a 3.5 variation that makes it available to all classes using an extension method.
public static bool IsSerializable(this object obj)
{
if (obj is ISerializable)
return true;
return Attribute.IsDefined(obj.GetType(), typeof(SerializableAttribute));
}
I took the answer on this question and the answer here and modified it so you get a List of types that aren't serializable. That way you can easily know which ones to mark.
private static void NonSerializableTypesOfParentType(Type type, List<string> nonSerializableTypes)
{
// base case
if (type.IsValueType || type == typeof(string)) return;
if (!IsSerializable(type))
nonSerializableTypes.Add(type.Name);
foreach (var propertyInfo in type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
{
if (propertyInfo.PropertyType.IsGenericType)
{
foreach (var genericArgument in propertyInfo.PropertyType.GetGenericArguments())
{
if (genericArgument == type) continue; // base case for circularly referenced properties
NonSerializableTypesOfParentType(genericArgument, nonSerializableTypes);
}
}
else if (propertyInfo.GetType() != type) // base case for circularly referenced properties
NonSerializableTypesOfParentType(propertyInfo.PropertyType, nonSerializableTypes);
}
}
private static bool IsSerializable(Type type)
{
return (Attribute.IsDefined(type, typeof(SerializableAttribute)));
//return ((type is ISerializable) || (Attribute.IsDefined(type, typeof(SerializableAttribute))));
}
And then you call it...
List<string> nonSerializableTypes = new List<string>();
NonSerializableTypesOfParentType(aType, nonSerializableTypes);
When it runs, nonSerializableTypes will have the list. There may be a better way of doing this than passing in an empty List to the recursive method. Someone correct me if so.
My solution, in VB.NET:
For Objects:
''' <summary>
''' Determines whether an object can be serialized.
''' </summary>
''' <param name="Object">The object.</param>
''' <returns><c>true</c> if object can be serialized; otherwise, <c>false</c>.</returns>
Private Function IsObjectSerializable(ByVal [Object] As Object,
Optional ByVal SerializationFormat As SerializationFormat =
SerializationFormat.Xml) As Boolean
Dim Serializer As Object
Using fs As New IO.MemoryStream
Select Case SerializationFormat
Case Data.SerializationFormat.Binary
Serializer = New Runtime.Serialization.Formatters.Binary.BinaryFormatter()
Case Data.SerializationFormat.Xml
Serializer = New Xml.Serialization.XmlSerializer([Object].GetType)
Case Else
Throw New ArgumentException("Invalid SerializationFormat", SerializationFormat)
End Select
Try
Serializer.Serialize(fs, [Object])
Return True
Catch ex As InvalidOperationException
Return False
End Try
End Using ' fs As New MemoryStream
End Function
For Types:
''' <summary>
''' Determines whether a Type can be serialized.
''' </summary>
''' <typeparam name="T"></typeparam>
''' <returns><c>true</c> if Type can be serialized; otherwise, <c>false</c>.</returns>
Private Function IsTypeSerializable(Of T)() As Boolean
Return Attribute.IsDefined(GetType(T), GetType(SerializableAttribute))
End Function
''' <summary>
''' Determines whether a Type can be serialized.
''' </summary>
''' <typeparam name="T"></typeparam>
''' <param name="Type">The Type.</param>
''' <returns><c>true</c> if Type can be serialized; otherwise, <c>false</c>.</returns>
Private Function IsTypeSerializable(Of T)(ByVal Type As T) As Boolean
Return Attribute.IsDefined(GetType(T), GetType(SerializableAttribute))
End Function
The exception object might be serializable , but using an other exception which is not.
This is what I just had with WCF System.ServiceModel.FaultException: FaultException is serializable but ExceptionDetail is not!
So I am using the following:
// Check if the exception is serializable and also the specific ones if generic
var exceptionType = ex.GetType();
var allSerializable = exceptionType.IsSerializable;
if (exceptionType.IsGenericType)
{
Type[] typeArguments = exceptionType.GetGenericArguments();
allSerializable = typeArguments.Aggregate(allSerializable, (current, tParam) => current & tParam.IsSerializable);
}
if (!allSerializable)
{
// Create a new Exception for not serializable exceptions!
ex = new Exception(ex.Message);
}

Categories