How to get default constructor when parameters are optional
The problem is that the C# compiler produces this:
public class B
{
// Methods
public B([Optional, DefaultParameterValue(0)] int i, [Optional, DefaultParameterValue("")] string str)
{
}
}
Something like below should work:
public static class TypeHelper {
public static ConstructorInfo GetDefaultConstructor<TType>() {
var type = typeof(TType);
return type.GetDefaultConstructor();
}
public static ConstructorInfo GetDefaultConstructor(this Type type) {
if(type == null) throw new ArgumentNullException("type");
var constructor = type.GetConstructor(Type.EmptyTypes);
if(constructor == null) {
var ctors =
from ctor in type.GetConstructors()
let prms = ctor.GetParameters()
where prms.All(p=>p.IsOptional)
orderby prms.Length
select ctor;
constructor = ctors.FirstOrDefault();
}
return constructor;
}
}
The problem is that optional parameters are nothing more than a compile time concept. You'll need to specify the constructor completely.
var ci = typeof(B).GetConstructor(new [] { typeof(int), typeof(string) });
You can write a help function that will invoke the constructor with the default values though. My example is not as robust as it should be but it should get you started.
static Func<T> CreateDefaultConstructor<T>(ConstructorInfo ci)
{
var l = new List<object>();
foreach (var p in ci.GetParameters())
{
if (p.IsOptional)
{
l.Add(p.RawDefaultValue);
}
}
return () => (T)ci.Invoke(l.ToArray());
}
Say I have the following class:
public class SomeClass
{
public SomeClass()
{
}
public SomeClass(int x)
{
}
public SomeClass(int x = 0, int y = 0)
{
}
}
Basically, you're asking for a query that will find the constructors that match constructor 1 and 3 above? If so, use this:
var constuctors = typeof(SomeClass).GetConstructors()
.Where(x => x.GetParameters().Count() == 0
|| x.GetParameters().Count(param => param.GetCustomAttributes(typeof(OptionalAttribute), false).Count() > 0) == x.GetParameters().Count());
Incredibly nasty query, but it gets the job done returning only 1 and 3 above.