0

I have a set of configuration objects whose constructors all take the same parameters. Is it possible to assign a constructor to a Func, or something similar, so that the constructor can be invoked in a generic way?

For example:

public class FooConfig : ConfigBase {
    public FooConfig(int a) { ... }
}

public class BarConfig : ConfigBase {
    public BarConfig(int a) { ... }
}

In calling code:

Func<int, ConfigBase> fooConfigCtr = FooConfig.FooConfig; // Obviously this doesn't work
FooConfig fooConfig = (FooConfig) fooConfigCtr(12345);

The calling code example is not to show the actual use, but just to show why I am having difficulty using Func for this case.

A workaround I have found is to provide a static Factory method on each class with the same signature, and have that call a private constructor. However it is slightly non-optimal.

Ryan Burbidge
  • 192
  • 3
  • 13
  • out of pure curiosity, what's wrong with using the conventional constructor itself? – Sebas May 23 '14 at 18:31
  • In the calling code we want to call the constructor in a generic way, which requires assigning a constructor to a Func or a factory method to a Func. – Ryan Burbidge May 23 '14 at 19:08

3 Answers3

3

You don't have to provide a static factory method. It may not be exactly what you want, but you could use a lambda expression, like this:

Func<int, ConfigBase> fooConfigCtr = n => new FooConfig(n);
p.s.w.g
  • 146,324
  • 30
  • 291
  • 331
  • 1
    Thanks, but I want to avoid the extra function/lambda – Ryan Burbidge May 23 '14 at 19:02
  • @user3339997 You can use a lambda expression, reflection, or factory method. Unfortunately, those are really your only options with C#, since you can't bind a delegate directly to a constructor. – p.s.w.g May 23 '14 at 19:08
0

Try this:

    Func<int, ConfigBase> fooConfigCtr = a => new FooConfig(a);
    FooConfig fooConfig = (FooConfig)fooConfigCtr(12345);

Without lambda expression you can try using the Activator.

    Type typeOfYourClass = typeof (FooConfig);
    FooConfig fooConfig = (FooConfig)Activator.CreateInstance(typeOfYourClass, 12345);
Bartosz Wójtowicz
  • 1,321
  • 10
  • 18
0

If you need a more dynamic way you can do it like this:

Func<int,ConfigBase> GetFactoryFunction(Type t)
{
    if(t == null) throw new ArgumentNullException("t");
    if(!typeof(ConfigBase).IsAssignableFrom(t)) throw new ArgumentException();

    return i => (ConfigBase)Activator.CreateInstance(t,i);
}

Or even generic:

Func<int,TDerived> GetFactoryFunction<TDerived>() where TDerived : ConfigBase
{
    return i => (TDerived)Activator.CreateInstance(typeof(TDerived),i);
}
CSharpie
  • 9,195
  • 4
  • 44
  • 71