# Can I somehow tidy up this (overuse?) of generics?

I'm building a generic flat file reader which looks something like this.

 public class GenericReader<TComposite, THeader, TData, TTrailer>
where TComposite : GenericComposite<THeader, TData, TTrailer>, new()
where TData : new()
where TTrailer : new()
{
{
// read stuff, do parsing etc
var composite = new TComposite();

composite.Data = new TData();
composite.Trailer = new TTrailer();

return composite;
}
}


It could be consumed like so.

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

Console.WriteLine(composite.Data.SomeProperty);



Here are the classes used.

public class Composite<THeader, TData, TTrailer> : GenericComposite<THeader, TData, TTrailer>
{

}

{

public TData Data { get; set; }

public TTrailer Trailer { get; set; }
}

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 how I could remove or encapsulate that generic type information in the GenericReader? I'm looking for an extra pair of eyes to show me something what I've been missing. We already did something with returning interfaces, and making the consumer do a cast, but that just moves the responsibility to the wrong location in my opinion, plus there is a small performance penalty.

Thanks.

-
What is the thinking behind the Composite and GenericComposite classes? They seem the same to me. –  Jeff Vanzella Nov 27 '12 at 19:05
What's the intent of the Composite class in the first place? Why is that separate from the GenericReader? –  Bobson Nov 27 '12 at 19:54
Composite class composites header, data and trailer, makes for one thing to return. You can see it as a logical file. –  JefClaes Nov 27 '12 at 19:57
@JeffVanzella You're absolutely right, it's not necessary. Now I can remove that first type parameter. –  JefClaes Nov 27 '12 at 20:39

Having so many new operations -- seems like you'd want to use some kind of a factory, injected in the constructor, or the instances themselves injected in the constructor, instead of constructing the classes inside the constructor.

-
The real imp uses a factory to create the instances. I'm doing more than composing my composite. –  JefClaes Nov 27 '12 at 19:50

Why not simply replace

public class GenericReader<TComposite, THeader, TData, TTrailer>
where TComposite : GenericComposite<THeader, TData, TTrailer>, new()
where TData : new()
where TTrailer : new()
{
{
// read stuff, do parsing etc
var composite = new TComposite();

composite.Data = new TData();
composite.Trailer = new TTrailer();

return composite;
}
}


with

public class GenericReader<THeader, TData, TTrailer>
where TData : new()
where TTrailer : new()
{
{
// read stuff, do parsing etc
var composite = new GenericComposite<THeader, TData, TTrailer>();

composite.Data = new TData();
composite.Trailer = new TTrailer();

return new composite;
}
}


?

-
Because I didn't see it. How can I look over that? Thank you, changing that right now. –  JefClaes Nov 27 '12 at 20:32
Sometimes, it just takes another pair of eyes. I've certainly been there, and that's exactly what this SE site is for! Glad to help. –  Bobson Nov 27 '12 at 22:30

I think the easiest way would be to create a factory type class. The create would take the 3 generics as generics, and the expected return type as a parameter. Then use reflection to create the instance. Before you say anything about using reflection, by creating generics in your function, you are inadvertently using reflection.

public class CompsiteFactory
{
where TData : new()
where TTrailer : new()
{
var finalType =
compositeType.MakeGenericType(new[] {typeof (THeader), typeof (TData), typeof (TTrailer)});

var compositeInstance =
Activator.CreateInstance(finalType);

compositeInstance.Data = new TData();
compositeInstance.Trailer = new TTrailer();

return compositeInstance;
}
}


public class GenericReader<THeader, TData, TTrailer>
where TData : new()
where TTrailer : new()
{

{
_factory = factory;
}

{
}
}

var factory = new CompsiteFactory();