Generics without new ()

I have a dozen methods in my project (C # 2.0) that look like this:

internal bool ValidateHotelStayEntity(DataRow row) { return (new HotelStayEntity(row)).Validate(); } 

... but for different entity classes. (Okay, not really, but I simplified the code here.)

He looks like a good candidate for generics, and I came up with this:

 internal bool ValidateEntity<T>(DataRow row) where T : EntityBase { return (new T(row)).Validate(); } 

And, of course, I get the message "I cannot create an instance of the Parameterer T parameter, because it does not have a new () error error.

The problem is that these โ€œentityโ€ classes do not have an open constructor without parameters, as well as a way to add โ€œrowโ€ data in the future. And since EntityBase is part of the structure of the company, I do not control it (i.e. I cannot change it).

Is there any way around this?

+7
source share
4 answers

Another way could be to include a reflection on the price of checking compilation time and lowering performance:

 internal bool ValidateEntity<T>(DataRow row) { object entity = Activator.CreateInstance(typeof(T), new object[] { row }); MethodInfo validate = typeof(T).GetMethod("Validate"); return (bool) validate.Invoke(entity, new object[]); } 

Note that this will work even if entities do not have a common ancestor

+3
source

One easy way is to provide a factory function:

 internal bool ValidateEntity<T>(DataRow row, Func<DataRow, T> factory) where T : EntityBase { return factory(row).Validate(); } 

and call with:

 bool valid = ValidateEntity(row, x => new Foo(x)); 

Remember that at this moment it is more difficult than just a challenge

 bool valid = new Foo(row).Validate() 

first of all...

Itโ€™s not entirely clear what you are trying to achieve in your real context, but such a factory / provider approach can certainly be useful at other times. Please note that calling a factory delegate can also be significantly faster than using new T() with a restriction as I wrote on my blog some time ago . Unusual in many cases, but worth knowing.

EDIT: for compatibility with .NET 2.0 you need to declare the delegate yourself, but this is easy:

 public delegate TResult Func<T, TResult>(T input); 

If you really use C # 2 (and not, say, C # 3, focus on .NET 2.0), you also wonโ€™t be able to use lambda expressions, but you can still use anonymous methods:

 bool valid = ValidateEntity(row, delegate(DataRow x) { return new Foo(x); }); 
+15
source

An example of solving the @JohnSaunders factory method:

 internal bool ValidateEntity<T>(DataRow row, Func<DataRow, T> factory) where T : EntityBase { return (factory(row)).Validate(); } 
+1
source

You can do something like this:

 internal bool ValidateEntity<T>(DataRow row) where T : EntityBase { return ((T)Activator.CreateInstance(typeof(T), new object[] { row })).Validate(); } 
+1
source

All Articles