Can I somehow remove this (excessive?) Generic?

I am creating a general flat reader that looks something like this.

public class GenericReader<TComposite, THeader, TData, TTrailer> where TComposite : GenericComposite<THeader, TData, TTrailer>, new() where THeader : new() where TData : new() where TTrailer : new() { public TComposite Read() { var composite = new TComposite(); composite.Header = new THeader(); composite.Data = new TData(); composite.Trailer = new TTrailer(); return composite; } } 

It can be used like this.

 var reader = new GenericReader<Composite<Header, Data, Trailer>, Header, Data, Trailer> (); var composite = reader.Read(); Console.WriteLine(composite.Data.SomeProperty); Console.ReadLine(); 

Here are the classes used.

 public class Composite<THeader, TData, TTrailer> : GenericComposite<THeader, TData, TTrailer> { } public class GenericComposite<THeader, TData, TTrailer> { public THeader Header { get; set; } public TData Data { get; set; } public TTrailer Trailer { get; set; } } public class Header { public string SomeProperty { get { return "SomeProperty"; } } } public class Data { public string SomeProperty { get { return "SomeProperty"; } } } public class Trailer { public string SomeProperty { get { return "SomeProperty"; } } } 

Is there a way to remove or encapsulate this generic type information in GenericReader? I am looking for an extra pair of eyes to show me what I was missing. We have already done something with the return of interfaces, and forcing the consumer to make the cast, but this just transfers responsibility to the wrong place, in my opinion, plus a slight decrease in performance.

Thanks.

Edit: I don't need TComposite, I can just return GenericComposite. How could I skip this?

 public class GenericReader<THeader, TData, TTrailer> where THeader : new() where TData : new() where TTrailer : new() { public GenericComposite<THeader, TData, TTrailer> Read() { var composite = new GenericComposite<THeader, TData, TTrailer>(); composite.Header = new THeader(); composite.Data = new TData(); composite.Trailer = new TTrailer(); return composite; } } public class GenericComposite<THeader, TData, TTrailer> { public THeader Header { get; set; } public TData Data { get; set; } public TTrailer Trailer { get; set; } } 
+6
source share
1 answer

It is not possible to remove the need for type declarations for the general constraints that you have.

However, your use case assumes this is the most common behavior:

 var reader = new GenericReader<Composite<Header, Data, Trailer>, Header, Data, Trailer>(); 

If this is the case, where you can make assumptions about the frequency of use of certain patterns, you can inherit a type (or set of types) from common classes with private types of definitions that can be used more easily.

In the above case, you can provide these classes for the basic, most common cases (in addition to general definitions):

 public class Composite : GenericComposite<Header, Data, Trailer> { } public class GenericReader : GenericReader< Composite, Header, Data, Trailer> { } 

which will then be used as follows:

 var reader = new GenericReader(); var composite = reader.Read(); Console.WriteLine(composite.Data.SomeProperty); Console.ReadLine(); 

You will still have types with typical parameters that will be used for highly specialized cases, but for general use cases (which you determine by analyzing / knowing the domain) you can determine what is the most common and provide classes with parameters of a given type.

+2
source

All Articles