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 (:
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.
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();
}
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);
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
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.