Reputation: 32640
I'd like to check if a type that is known at runtime provides a parameterless constructor. The Type
class did not yield anything promising, so I'm assuming I have to use reflection?
Upvotes: 118
Views: 40966
Reputation: 18749
If anyone is interested in an "official" version, the following code exists in the System.Activities.Presentation.TypeUtilities
class, in the .NET Framework WPF base class library System.Activities.Presentation.dll, Version=4.0.0.0:
public static bool CanCreateInstanceUsingDefaultConstructor(this Type t) =>
t.IsValueType ||
!t.IsAbstract && t.GetConstructor(Type.EmptyTypes) != null;
Notice the check for t.IsAbstract
, which is not mentioned elsewhere on this page. This property is true for .NET interface types as well as static and abstract reference types.
You can also expand the GetConstructor
call inline, if you feel like micro-optimizing away one stack frame, or if you need the method to work on BindingFlags.NonPublic
types as well:
public static bool CanCreateInstanceUsingDefaultConstructor(this Type t) =>
t.IsValueType ||
!t.IsAbstract && t.GetConstructor( // v-- includes 'private' classes
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
null,
Type.EmptyTypes,
null) != null;
Upvotes: 5
Reputation: 1101
To get the one that has more optional parameters or an empty constructor at all, use:
typeof(myClass)
.GetConstructors()
.OrderBy(x => x.GetParameters().Length - x.GetParameters().Count(p => p.IsOptional))
.FirstOrDefault();
Upvotes: 1
Reputation: 5876
I needed to count constructors with only optional parameters the same as true parameter-less constructors. To do this:
myClass.GetType().GetConstructors()
.All(c => c.GetParameters().Length == 0 || c.GetParameters().All(p => p.IsOptional))
Upvotes: 4
Reputation: 10205
The Type
class is reflection. You can do:
Type theType = myobject.GetType(); // if you have an instance
// or
Type theType = typeof(MyObject); // if you know the type
var constructor = theType.GetConstructor(Type.EmptyTypes);
It will return null if a parameterless constructor does not exist.
If you also want to find private constructors, use the slightly longer:
var constructor = theType.GetConstructor(
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
null, Type.EmptyTypes, null);
There's a caveat for value types, which aren't allowed to have a default constructor. You can check if you have a value type using the Type.IsValueType
property, and create instances using Activator.CreateInstance(Type)
;
Upvotes: 205
Reputation: 73163
type.GetConstructor(Type.EmptyTypes) != null
would fail for struct
s. Better to extend it:
public static bool HasDefaultConstructor(this Type t)
{
return t.IsValueType || t.GetConstructor(Type.EmptyTypes) != null;
}
Succeeds since even enum
s have default parameterless constructor. Also slightly speeds up for value types since the reflection call is not made.
Upvotes: 20
Reputation: 273169
Yes, you have to use Reflection. But you already do that when you use GetType()
Something like:
var t = x.GetType();
var c = t.GetConstructor(new Type[0]);
if (c != null) ...
Upvotes: 13
Reputation: 71565
Depending on your situation, you could also use a generic type restriction:
public void DoSomethingWith<T>(T myObject) where T:new() {...}
The above method declaration will restrict the parameter type to any Object that can be instantiated with a parameterless constructor. The advantage here is that the compiler will catch any attempt to use the method with a class that doesn't have a parameterless constructor, so as long as the type is known SOMEWHERE at compile-time, this will work and will alert you to a problem earlier.
Of course if the type really is known only at runtime (i.e. you're using Activator.CreateInstance() to instantiate an object based on a string or a constructed Type) then this won't help you. I generally use reflection as the absolute last option, because once you've gone to dynamic land you pretty much have to stay in dynamic land; it's usually difficult or even messier to dynamically instantiate something and then start dealing with it statically.
Upvotes: 4
Reputation: 160852
This should work:
myClass.GetType().GetConstructors()
.All(c=>c.GetParameters().Length == 0)
Upvotes: 10
Reputation: 381
Yes, you have to use reflection.
object myObject = new MyType();
Type type = myObject.GetType();
ConstructorInfo conInfo = type.GetConstructor(new Type[0]);
Upvotes: 2