开发者

checking beforehand if `System.Activator.CreateInstance(Of T)` will fail

开发者_C百科I have a type (Human) and I want to know if I could do System.Activator.CreateInstance(Of Human)(). So basically I want to check if Human has a public parameterless constructor / or a public constructor with optional parameters that make it possible to call New Human without giving any arguments.

Is it possible to check beforehand if System.Activator.CreateInstance(Of T) will fail? (I mean other than wrapping the statement System.Activator.CreateInstance(Of Human)() in a Try Catch of course..)

I've tried this but it doesn't work:

Option Strict On : Option Explicit On
Module Test
    Public Class Human
        Public Sub New(Optional ByVal a As Integer = 1)

        End Sub
    End Class
    Public Sub Main()
        Dim c = GetType(Human).GetConstructor(System.Type.EmptyTypes)
        MsgBox(c Is Nothing)
    End Sub
End Module


To check if the constructor is empty or all paramters are optional:

var hasEmptyOrDefaultConstr = 
  typeof(Human).GetConstructor(Type.EmptyTypes) != null || 
  typeof(Human).GetConstructors(BindingFlags.Instance | BindingFlags.Public)
    .Any (x => x.GetParameters().All (p => p.IsOptional));


You can check and make sure your type Human has an accessible parameterless constructor. Easiest way to do is create a generic method and add a constraint where T : new()

EDIT:

You can manually check for parameterless constructor like this

if(typeof(Human).GetType().GetConstructor(Type.EmptyTypes) !=null)
{
  ...      
}


Please note, that Activator.CreateInstance<T>() or Activator.CreateInstance(Type) will only work with parameterless constructors. A constructor with only optional arguments is not parameterless in that sense.

Optional parameters (or arguments) are resolved by the C# compiler on the call site. However, there is no compiler involved in such a way when invoking the constructor using reflection.

If you use the following code, you'll get a MissingMethodException saying that there is no parameterless constructor defined:

namespace ConsoleApplication1
{
    public class Foo
    {
        public Foo(int optional = 42)
        {
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Activator.CreateInstance<Foo>(); // causes MissingMethodException
        }
    }
}

In other words optional arguments are a compiler thing, not a CLR thing.

For more information about "corner cases with optional arguments" see this recent blog series of Eric Lippert:

http://ericlippert.com/2011/05/09/optional-argument-corner-cases-part-one/

Having that said, you might be able to somehow replicate the desired behavior using some more reflection and manually creating the required parameters for the constructor call. The compiler will place some attributes inside the assembly which you could use for that purpose, I guess.

Example:

public class Foo
{
    public Foo([Optional, DefaultParameterValue(5)] int optional)
    {
        Console.WriteLine("Constructed");
    }
}


I created a quick console app using reflection to test for parameter-less constructors on types. Is this what you need?

using System;
using System.Linq;

namespace ConsoleApplication
{
    public class HasPublicParameterlessContructorClass
    {
    }

    public class DoesntHavePublicParameterlessContructorClass
    {
        private int someField;

        public DoesntHavePublicParameterlessContructorClass(int someParameter)
        {
            someField = someParameter;
        }
    }

    class Program
    {
        public static bool HasPublicParameterlessContructor(Type t)
        {
            return t.GetConstructors().Any(constructorInfo => constructorInfo.GetParameters().Length == 0);
        }

        static void Main()
        {
            Console.WriteLine(HasPublicParameterlessContructor(typeof(HasPublicParameterlessContructorClass)));
            Console.WriteLine(HasPublicParameterlessContructor(typeof(DoesntHavePublicParameterlessContructorClass)));
        }
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜