Reputation: 53
I have this method that creates an instance of a class, measures the time it takes to load the class, and has the option to call a method. I'm currently trying to implement the option to pass parameters to the constructor of this method (IE T
) but I'm a bit stuck, can anyone help?
public static T CreateInstanceOf<T>(Action<T> configure = null) where T : new()
{
var stopwatch = Stopwatch.StartNew();
var result = new T();
configure?.Invoke(result);
stopwatch.Stop();
Logger.Trace("Loaded " + result.GetType().Name + " [took " + stopwatch.ElapsedMilliseconds + "ms]");
return result;
}
Upvotes: 1
Views: 131
Reputation: 29207
It's much easier if you keep the work of creating class instances out of this method, since the purpose isn't really to create objects - you just want to time the constructors. You could write your method like this instead:
public T TimeCreationOf<T>(Func<T> creator, Action<T> configure = null)
{
var stopwatch = Stopwatch.StartNew();
var result = creator.Invoke();
configure?.Invoke(result);
stopwatch.Stop();
Logger.Trace("Loaded " + result.GetType().Name + " [took " + stopwatch.ElapsedMilliseconds + "ms]");
return result;
}
(Since you're just timing, do you need this method to return the instance of T
that was created?)
Now what you pass into this method is a function that returns a T
. And since what you want to time is the constructor, you can just pass in a function that calls the constructor and returns an instance of T
.
This makes it much easier because you don't need the new()
constraint - T
could be any type with any sort of constructor. And you don't need to worry about how the "timing" method will call the constructors - the functions you're passing in do that for you:
TimeCreationOf(() => new ClassOne());
TimeCreationOf(() => new ClassTwo(5, "X"));
Because you're calling the constructors directly you know exactly which constructor you want to call and what to pass to it. If you tried to write a generic method that could create all sorts of objects it would be really difficult.
And if you still need to pass in another Action<T>
that performs some additional configuration on the object (and you want to include that in the timing) you can do that as well.
TimeCreationOf(() => new ClassTwo(), c =>
{
c.SomeProperty = "x";
c.DoSomethingElse();
});
Upvotes: 1
Reputation: 152521
T
is not a method - it's a generic type, that you have required have a parameterless constructor, which you are calling. Since there's not a syntax to specify that the type implement a specific constructor signature, you're left with two options:
Activator.CreateInstance
) to pass parameters to the constructor and hope that whatever T
is at runtime supports those parameters, orRequire that T
implement some interface that you can use to initialize the object:
public interface IInitializable
{
public void Init(...parameters...)
}
public static T CreateInstanceOf<T>(Action<T> configure = null) where T : new(), IInitializable
{
T = new T();
T.Initialize(...parameters...);
...
}
Upvotes: 0