views:

876

answers:

6

I want to handle different types of docs the same way in my application Therefore: I have a generic interface like this.

public interface IDocHandler<T>where T: class
{

T Document { get;set;}

void Load(T doc);

void Load(string PathToDoc);

void Execute();

void Execute(T doc);

}

And for different types of documents I implement this interface.

for example:

public class FinanceDocumentProcessor:IDocumentHandler<ReportDocument>
{} 


public class MarketingDocumentProcessor:IDocumentHandler<MediaDocument>
{}

Then I can do of course something like this:

IDocumentHandler<ReportDocument> docProc= new FinanceDocumentProcessor();

It would be interessting to know how I could inject T at runtime to make the line above loosly coupled...

IDocumentHandler<ReportDocument> docProc = container.resolve("FinanceDocumentProcessor());

but I want to decide per Configuration wether I want to have my FinanceDomcumentProcessor or my MarketingDocumentProcessor... therefore I would have to inject T on the left site, too ... Since I have to use c# 2.0 I can not use the magic word "var" which would help a lot in this case... but how can I design this to be open and flexible...

Thanks for any help

F.

A: 

You might want to look into using the Unity framework on CodePlex. Unity is released as sourcecode (and runs on .NET 2), so you can implement Dependency Injection in your application.

Pete OHanlon
A: 

You need to use a non-generic interface on the left side.

Try:

public interface IDocumentHandler { }
public interface IDocumentHandler<T> : IDocumentHandler { }

This will create two interfaces. Put everything common, non-T-specific into the base interface, and everything else in the generic one.

Since the code that you want to resolve an object into, that you don't know the type of processor for, you couldn't call any of the T-specific code there anyway, so you wouldn't lose anything by using the non-generic interface.


Edit: I notice my answer has been downvoted. It would be nice if people downvoting things would leave a comment why they did so. I don't care about the reputation point, that's just minor noise at this point, but if there is something seriously wrong with the answer, then I'd like to know so that I can either delete the answer (if it's way off target) or correct it.

Now in this case I suspect that either the original questionee has downvoted it, and thus either haven't posted enough information, so that he's actually asking about something other than what he's asked about, or he didn't quite understand my answer, which is understandable since it was a bit short, or that someone who didn't understand it downvoted it, again for the same reason.

Now, to elaborate.

You can't inject anything "on the left side". That's not possible. That code have to compile, be correct, and be 100% "there" at compile-time. You can't say "we'll tell you what T is at runtime" for that part. It just isn't possible.

So the only thing you're left with is to remove the T altogether. Make the code that uses the dependency not depend on T, at all. Or, at the very least, use reflection to discover what T is and do things based on that knowledge.

That's all you can do. You can't make the code on the left side change itself depending on what you return from a method on the right side.

It isn't possible.

Hence my answer.

Lasse V. Karlsen
+2  A: 

I think that with your current design, you are creating a "dependency" between IDocumentHandler and a specific Document (ReportDocument or MediaDocument) and so if you want to use IDocumentHandler<ReportDocument or MediaDocument> directly in your code you must assume that your container will give you just that. The container shouldn't be responsible for resolving the document type in this case.

Would you consider changing your design like this?

public interface IDocumentHandler
{
    IDocument Document { get; set; }

    void Load(IDocument doc);

    void Load(string PathToDoc);

    void Execute();

    void Execute(IDocument doc);

}

public class IDocument { }
public class ReportDocument : IDocument { }
public class MediaDocument : IDocument { }
public class FinanceDocumentProcessor : IDocumentHandler { }
public class MarketingDocumentProcessor : IDocumentHandler { }
bruno conde
+1  A: 

Sorry for the missunderstanding and thanks for all the comments but I have another example for my challange (maybe I am using the wrong design for that) ... But I give it a try: Same Situtation but different Explanation Example: Image I have: ReportingService, Crystal, ListAndLabel Three different Reporting Documenttypes. I have a gerneric Handler IReportHandler (would be the same as above) this Handler provides all the functionality for handling a report Document. for Example

ChrystalReportHandler:IReportHandler<CrystalReportDocument>

Now I want to use a Framework like Unity (or some else framework) for dependency injection to decide via configuration whether I want to use Crystal, Reportingservices or List and Label.

When I specify my mapping I can inject my ChrystalReportHandler but how can I inject T on the left side or in better word The Type of ReportDocument.

IReportHandler<T (this needs also to be injected)> = IOContainer.Resolve(MyMappedType here)

my Problem is the left Site of course because it is coupled to the type but I have my mapping ... would it be possible to generate a object based on Mapping and assign the mapped type ? or basicaly inject T on the left side, too? Or is this approach not suiteable for this situation...

Thanks Regards

F.

+1  A: 

If I understand you correctly, you have two options.

  1. if you have interface IDocHandler and multiple classes implementing it, you have to register each type explicitly, like this:

    container.AddComponent>(typeof(FooHandler));

  2. if you have one class DocHandler you can register with component using open generic type

    container.AddComponent(typeof(IDocHandler<>), typeof(DocHandler<>));

then each time you resolve IDocHandler you will get an instance of DocHandler and when you resolve IDocHandler you'll get DocHandler

hope that helps

Krzysztof Koźmic
A: 

Take a look at this:

link text

Shay Jacoby