Question

Is it possible at all to check if a type has a parameterless constructor, in order to cast it and call a method which requires a parameterless constructor with the : new() constraint?

Being only able to only check that a type as a public parameterless as answered here would not be enough as it would not allow calling the target methods.

The objective is to have the following logic, where IInteresting objects do not implement a public parameterless constructor and need to be converted before calling Save1:

    public interface IInteresting { }

    public void Save<T>(T o) {
        var oc = o as (new()); /* Pseudo implementation */
        if (oc != null) {
            this.Save1(oc);
        }
        else {
            var oi = o as IInteresting;
            if (oi != null) {
                this.Save2(oi);
            }
        }
    }

    private void Save1<T>(T o) where T : new() {
        //Stuff
    }

    private void Save2<T>(IInteresting o) {
        //Stuff to convert o to a DTO object with a public parameterless constructor, then call Save1(T o)
    }

Of course if I could make Save1 and Save2 share the same signature that would solve the issue, but I cannot find a way to do so as the following will not compile (in Routine, Save will call the first implementation instead of the second):

    public void Routine<T>(T o) {
        var oi = o as IInteresting;
        if (oi != null) {
            this.Save(oi);
        }
    }

    private void Save<T>(T o) where T : new() {
        //Stuff
    }

    private void Save<T>(IInteresting o) {
        //Stuff to convert o to a DTO object with a public parameterless constructor, then call Save(T o)
    }
Was it helpful?

Solution

Based on your comments, I imagine you have an object of an unknown type that you want to pass to a generic function that requires the passed-over object to be of the generic type argument, which has to have a parameterless constructor. Hence, for the time being, we can assume that your function Save1<T>(T) from your question is that function, not written by you, not possible to be changed.

A solution to this would be to make the call by using reflection:

OTHER TIPS

Another possible solution, depending on what you do inside private void Save<T>(T o) where T : new() is to use ICloneable interface. Or introduce yours (as I've said, it depends on Save's contents):

interface IConstructible
{
    object Construct();
}

And have:

private void Save1<T>(T o) where T : ICloneable {

Of course this is just a workaround - O. R. Mapper's answer gives the only direct solution.

using System.Reflection;


public static class Generics {
 public static void T0<T> ( T obj ) where T : new () {
  Console.WriteLine ( "{0} {1}", obj, obj.GetType () );
 }

 public static void T1<T> ( T obj ) {
  MethodInfo mi = GenericMethodInfo ( typeof ( Generics ), "T0", typeof ( T ) );
  mi.Invoke ( null, new object[] { obj } );
 }

 public static MethodInfo GenericMethodInfo ( Type classType, string methodName, Type genericType ) {
  return classType.GetMethod ( methodName ).MakeGenericMethod ( genericType );
 }
}


Generics.T0 ( 123 );
Generics.T1 ( 123 );
// Impossible.. Generics.T0 ( "12345" );
Generics.T1 ( "12345" );
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top