1

I'm looking for a way faster than Activator.CreateInstance to instantiate a class from its type.

I'm doing it this way for now: Activator.CreateInstance(typeof(LoginView)); but it's extremly slow: I see some lags while instantiating different views.

A suggestion for me ? I'm googling it for hours now and I did not find out an faster way than this to doing what I want.. :/

Thanks a lot (:

dotixx
  • 1,490
  • 12
  • 23
  • 2
    `new LoginView()` should work. Or do I miss something? – Cédric Bignon Jul 24 '13 at 19:40
  • 1
    Cached a compiled delegate that calls the ctor. – SLaks Jul 24 '13 at 19:41
  • 1
    I suppose `typeof(LoginView)` is not the actual argument, or else you could just have written `new LoginView()`, as Cédric suggests. But in any case, are you sure that lag is coming from the reflection layer and not from the `LoginView` constructor itself? – Frédéric Hamidi Jul 24 '13 at 19:42
  • 1
    What do you mean by "extremely slow"? I don't think that the problem is with Activator.CreateInstance - how many times it is called and how long it takes? – empi Jul 24 '13 at 19:42
  • @FrédéricHamidi yup i receive a `Type` containing the result of typeof(...) :) – dotixx Jul 24 '13 at 19:43
  • @FrédéricHamidi it's faster by using `new LoginView()` so I guess it's not only the ctor .. – dotixx Jul 24 '13 at 19:46
  • The generic `new T()` is just again reflection (for reference type). See http://stackoverflow.com/questions/6708459/given-where-t-new-does-new-t-use-activator-createinstance-internally. You need to go the expression route, see this: http://stackoverflow.com/q/6582259/661933 – nawfal Sep 13 '13 at 06:33

4 Answers4

5

You can use Linq Expressions as explained in this blog post. In your case, it would be

ConstructorInfo ctor = typeof(LoginView).GetConstructors().First();
ObjectActivator<LoginView> createdActivator = GetActivator<LoginView>(ctor);


LoginView instance = createdActivator();

In case the link goes down, this is ObjectActivator delegate

delegate T ObjectActivator<T>(params object[] args);

and the GetActivator method

public static ObjectActivator<T> GetActivator<T>
    (ConstructorInfo ctor)
{
    Type type = ctor.DeclaringType;
    ParameterInfo[] paramsInfo = ctor.GetParameters();                  

    //create a single param of type object[]
    ParameterExpression param =
        Expression.Parameter(typeof(object[]), "args");

    Expression[] argsExp =
        new Expression[paramsInfo.Length];            

    //pick each arg from the params array 
    //and create a typed expression of them
    for (int i = 0; i < paramsInfo.Length; i++)
    {
        Expression index = Expression.Constant(i);
        Type paramType = paramsInfo[i].ParameterType;              

        Expression paramAccessorExp =
            Expression.ArrayIndex(param, index);              

        Expression paramCastExp =
            Expression.Convert (paramAccessorExp, paramType);              

        argsExp[i] = paramCastExp;
    }                  

    //make a NewExpression that calls the
    //ctor with the args we just created
    NewExpression newExp = Expression.New(ctor,argsExp);                  

    //create a lambda with the New
    //Expression as body and our param object[] as arg
    LambdaExpression lambda =
        Expression.Lambda(typeof(ObjectActivator<T>), newExp, param);              

    //compile it
    ObjectActivator<T> compiled = (ObjectActivator<T>)lambda.Compile();
    return compiled;
}

One advantage to using this method over the generic method is that you can easily pass in parameters to your constructor but the disadvantage being more verbose code.

keyboardP
  • 68,824
  • 13
  • 156
  • 205
2

You could use generics.

T MyActivator<T>() where T : new() { return new T(); }

T MyActivator<T>(T variable) where T : new() { return new T(); }

The first one is used if you know the type (explicitly use the type).
The second one is used to infer the type from a variable:

MyType blah = MyActivator<MyType>();

SomeType someVar;
object blah = MyActivator(someVar);
Yochai Timmer
  • 48,127
  • 24
  • 147
  • 185
  • If he receives a Type containing the result of typeof, as he says in his comment, this wont work. – fcuesta Jul 24 '13 at 20:02
  • -1, `new T()` is just again reflection (for reference type). See http://stackoverflow.com/questions/6708459/given-where-t-new-does-new-t-use-activator-createinstance-internally. You need to go the expression route, see this: http://stackoverflow.com/q/6582259/661933 – nawfal Sep 13 '13 at 06:31
1

EDIT It appears the type is generic, and not just LoginView. You could try this:

public void Foo<T>(T input) where T : new()
{
    var myInstance = new T();
}
Alden
  • 6,553
  • 2
  • 36
  • 50
1

Instead of taking a Type that returns the result of typeof, take a delegate that gets you an instance of the object:

Func<object> myActivator = () => new LoginView();

Maybe even have a method to help you do that, if it'd make it easier on your code:

public static Func<object> GetActivator<T>() where T : new()
{
    return () => new T();
}

This will have a very small overhead for calling the Func delegate. Should be much faster than calling Activator.CreateInstance on a Type.

Tim S.
  • 55,448
  • 7
  • 96
  • 122