How do I check if a type provides a parameterless constructor?
I'd like to che开发者_JAVA技巧ck 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?
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)
;
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.
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) ...
This should work:
myClass.GetType().GetConstructors()
.All(c=>c.GetParameters().Length == 0)
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.
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))
If anyone is interested in an "official" version, the following was found via .NET Reflector:
from: System.Activities.Presentation.TypeUtilities
in 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.
You can also expand the GetConstructor
call out as follows, if you feel like micro-optimizing away one stack frame:
…t.GetConstructor(BindingFlags.Public|BindingFlags.Instance, null, Type.EmptyTypes, null)…
Yes, you have to use reflection.
object myObject = new MyType();
Type type = myObject.GetType();
ConstructorInfo conInfo = type.GetConstructor(new Type[0]);
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();
精彩评论