3

I have 2 types of objects, Database models and normal system models.

I want to be able to convery the model into Database model and vice versa.

I have the following method I wrote:

 public static E FromModel<T, E>(T other) 
            where T : sysModel
            where E : dbModel
{
     return new E(other);
}

basically both sysModel and dbModel are abstract.

dbModel have lots of inherting classes which all have copy constructors.

Im receiving :

Cannot create an instance of type parameter 'E' becauase it does not have the new() constraint

Im aware that technically sometimes I dont have a matching constructor for every value of T, at least that whats the debugger know.

I also tried adding the where E : dbModel, new() constraint, but its just irrelevant.

Is there a way to convert model into another model using generic method and using parameters?

Thanks.

Ori Refael
  • 2,888
  • 3
  • 37
  • 68
  • 1
    The `new()` constraint is for specifying the type has a constructor with no parameters. You probably need to introduce some sort of generic factory method via an interface which exposes the type of copy construction you want. – Anthony Jun 01 '16 at 13:47
  • I know, i really want to avoid passing the constructor as argument – Ori Refael Jun 01 '16 at 13:48
  • 1
    You cannot impose the existence of a constructor with parameters upon generic type arguments. You're left with using `Activator.CreateInstance` to do so and pray that the types used have a matching constructor. Typically, solutions using generic types should refrain from this kind of thing because you're imposing a hard dependency on the implementation. This is sort of like saying "I want this method to be able to construct any type of storage class, *ANY TYPE*, but it has to have a string parameter in the constructor and it has to be a filename". – Lasse V. Karlsen Jun 01 '16 at 13:48
  • 1
    Instead you should impose the existence of a factory object that has a method that take the right type of parameter and construct the object you should use. This way you're at least moving that hard dependency one level away from the actual type. – Lasse V. Karlsen Jun 01 '16 at 13:49
  • Note that the generic parameter `T` is irrelevant since it's not used directly. You can just substitute it with `sysModel`. – D Stanley Jun 01 '16 at 13:50
  • Or you should just place the method in the type it belongs in, the right type, and implement it to take the right type of input. I'm assuming there is a 1-to-1 relationship between the type to convert from and the type to convert to. In this case simply place a static method in each type with the right parameter and output type. – Lasse V. Karlsen Jun 01 '16 at 13:51
  • Thanks for the comments guys, i see what you mean. Stanly, also thanks for pointing this out. – Ori Refael Jun 01 '16 at 13:55
  • Here i think some helpfull related post https://stackoverflow.com/questions/3364447/c-sharp-generic-methods-type-parameters-in-new-constructor-constraint?rq=1 – layonez Jun 01 '16 at 13:59
  • @LayonezWronskey i saw this post, but i really wanted to avoid passing constructor as argument – Ori Refael Jun 01 '16 at 14:01

1 Answers1

6

To use new on a generic type, you would have to specify the new() constraint on your class/method definition:

public static E FromModel<T, E>(T other) 
        where T : sysModel
        where E : dbModel, new()

Since you are using a parameter in the constructor, you can't use new, but you can use the Activator instead and pass other as an argument:

public static E FromModel<T, E>(T other)
    where T : sysModel
    where E : dbModel
{
    return (E)Activator.CreateInstance(typeof(E), new[]{other});
}
Manfred Radlwimmer
  • 13,257
  • 13
  • 53
  • 62
  • seems to compile. what would crash it? it seems like every sort of exception can be thrown. I understand that it must find a matching constructor that uses T, right? – Ori Refael Jun 01 '16 at 13:54
  • Exactly. If `E` doesn't have a constructor that takes a single parameter `T`, than it will throw an exception. – Manfred Radlwimmer Jun 01 '16 at 13:55
  • awesome, i want it to happen either way to prevent bugs and holes in db.ill accept in 2 minutes, when i can – Ori Refael Jun 01 '16 at 13:56