Implementing open closed principle using generics - c#

I'm new to using SOLID so please excuse my lack of correct terminology, correct me, if needed I am looking to learn :-)
I am in the process of upgrading a library and wanted to use the Open Closed principle, for reason of extensibility without having to modify the provider.
The library intention is to provide a list of modules based on a view type. Based on the type the query and conditions to retrieve the modules is different. Below is an simplied version of the current code:
public class ModuleProvider
{
public List<ITreeNode> GetModules(ViewType viewType)
{
switch (viewType)
{
case ViewType.Classes
//build query here that returns List<TreeNode> for classes
return modules;
case ViewType.Queries
//build query here that returns List<TreeNode> for queries
return modules;
}
}
}
I have read that using the switch statement for examples such as above are bad. I understand why because if I was to add a new ViewType the GetModules will need to change.
I think I have to create an interface that has a GetModules function and then create a class for each i.e a QueryModules and ClassModules class to return then specific list. However, I'm stuck on how will the provider above will need to change to support this? I'm I correct in thinking I will need to use generics for this?
public interface IModuleProvider
{
List<ITreeNode> GetModules();
}
public class QueryModuleProvider : IModuleProvider
{
public List<ITreeNode> GetModules()
{
return new List<ITreeNode>() { new TreeNode() { Type = "Query Module" } };
}
}
public class ClassModuleProvider : IModuleProvider
{
public List<ITreeNode> GetModules()
{
return new List<ITreeNode>() {new TreeNode() { Type = "Class Module"}};
}
}
Am I on the right track? Any help the clever members of stackoverflow can give will be much appreciated.
Thanks

That approach should be fairly obvious that it's not the same - you've changed List<ITreeNode> GetModules(ViewType viewType) to List<ITreeNode> GetModules(). You're now not asking one class for the modules, but you need to decide between two classes - which is exactly the situation you started with. This is a "chicken or the egg" problem.
Instead you should inject in to your a way to dynamically decide how to build your tree nodes.
Here's an approach:
public class ModuleProvider
{
private Dictionary<ViewType, Func<List<ITreeNode>>> _factory;
public ModuleProvider(Dictionary<ViewType, Func<List<ITreeNode>>> factory)
{
_factory = factory;
}
public List<ITreeNode> GetModules(ViewType viewType)
{
return _factory[viewType]();
}
}
When you create the ModuleProvider you're injecting in the dictionary of factories to produce the tree nodes. You can build that dictionary in a myriad of ways without the need to recompile the assembly.

Related

Get instance of a class using generics

I'm working on a game that uses MVCS and has, so far, clearly separated the business logic from the view.
However, I've been having trouble with one particular piece of the puzzle.
In the game we have command classes (IPlayerCommand) that execute a specific business logic. Each command class returns a result class (PlayerCommandResult). For each PlayerCommand we have a respected visual command class (IVisualPlayerCommand) that takes the PlayerCommandResult and updates the view accordingly.
I'd like the IVisualPlayerCommand to use specific classes that inherit PlayerCommandResult in order to get the information it needs (as opposed to using object). I'd also like to make it compile-time safe (as opposed to casting it before using it). For these two reasons I made the classes use generics.
Here are the declaration of the classes:
public class PlayerCommandResult
{}
public interface IPlayerCommand<T> where T : PlayerCommandResult
{
T Execute(GameWorld world);
}
public interface IVisualPlayerComamnd<T> where T : PlayerCommandResult
{
void Play(T commandResult);
}
Here is the Move Unit command as an example:
public class MoveUnitPlayerCommand : IPlayerCommand<MoveUnitPlayerCommandResult>
{
private Unit unitToMove;
public MoveUnitPlayerCommand(Unit unit)
{
this.unitToMove = unit;
}
public MoveUnitPlayerCommandResult Execute(GameWorld world)
{
MoveUnitPlayerCommand result = new MoveUnitPlayerCommand();
// Do some changes to the world and store any information needed to the result
return result;
}
}
public class MoveUnitVisualPlayerCommand : IVisualPlayerCommand<MoveUnitPlayerCommandResult>
{
void Play(MoveUnitPlayerCommandResult commandResult)
{
// Do something visual
}
}
public class MoveUnitPlayerCommandResult : PlayerCommandResult
{
public Unit TargetUnit { get; private set; }
public Path MovePath { get; private set; }
}
So far, so good. However, I'm having a really hard time tying a IPlayerCommand to a IVisualPlayerCommand because of the use of generics:
public class CommandExecutorService
{
public void ExecuteCommand<T>(IPlayerCommand<T> command) where T : PlayerCommandResult
{
T result = command.Execute(world);
IVisualPlayerCommand<T> visualCommand = GetVisualPlayerCommand(command);
visualCommand.Play(result);
}
public IVisualPlayerCommand<T> GetVisualPlayerCommand<T>(IPlayerCommand<T> command) where T : PlayerCommandResult
{
// ?!?!?!?!?!??!?!?!??!?!
}
}
I have a feeling that what I'm trying to do is not even possible because of the way generics work in C# (as opposed to Java where I could say IVisualPlayerCommand<?>).
Could you help me figure out a way?
Any feedback for the design is welcome.
P.S. Sorry if the title doesn't reflect the question. I wasn't sure how to boil down the question in one line.
P.P.S. Which is why I also don't know if this question has been asked and answered before.
You two command classes, are served as service. To me, for this case, I would use the service locator pattern. As how to implement this pattern, you can check this link
The drawback of using template, is that, if something changes, you have to compiled it again.
Here's link which provides an example of the service locator pattern.
So for you code, you want find the corresponding instance of IVisualPlayerCommand to IPlayerCommand, so the concrete service can inherit from both interface, which it actually implements the IVisualPlayerCommand interface, while the IPlayerCommand just severs as a tag.
so the code will like this:
class MoveUnitVisualPlayerCommand: IVisualPlayerCommand, IPlayerCommand {}
services = new Dictionary<object, object>();
this.services.Add(typeof(IPlayerCommand ), new MoveUnitVisualPlayerCommand());
as how to get the service, you can refer the example.
Hope this helps.

Can I use more generic interfaces to simplify my classes to use a command pattern?

I'm trying to make an app I'm designing more generic and implement the command pattern into it to use manager classes to invoke methods exposed by interfaces.
I have several classes with the GetItem() and GetList() methods in them, some are overloaded. They accept different parameters as I was trying to use dependency injection, and they return different types. Here are a couple of examples:
class DatastoreHelper
{
public Datastore GetItem(string DatastoreName)
{
// return new Datastore(); from somewhere
}
public Datastore GetItem(int DatastoreID)
{
// return new Datastore(); from somewhere
}
public List<Datastore> GetList()
{
// return List<Datastore>(); from somewhere
}
public List<Datastore> GetList(HostSystem myHostSystem)
{
// return List<Datastore>(); from somewhere
}
}
class HostSystemHelper
{
public HostSystem GetItem(int HostSystemID)
{
// return new HostSystem(); from somewhere
}
public List<HostSystem> GetList(string ClusterName)
{
//return new List<HostSystem>(); from somewhere
}
}
I'm trying to figure out if I could use a generic interface for these two methods, and a manager class which would effectively be the controller. Doing this would increase the reuse ability of my manager class.
interface IGetObjects
{
public object GetItem();
public object GetList();
}
class GetObjectsManager
{
private IGetObjects mGetObject;
public GetObjectsManager(IGetObjects GetObject)
{
this.mGetObject = GetObject;
}
public object GetItem()
{
return this.mGetObject.GetItem();
}
public object GetList()
{
return this.GetList();
}
}
I know I'd have to ditch passing in the parameters to the methods themselves and use class properties instead, but I'd lose the dependency injection. I know I'd have to cast the return objects at the calling code into what they're supposed to be. So my helper classes would then look like this:
class DatastoreHelper
{
public string DatastoreName { get; set; }
public string DatastoreID { get; set; }
public object GetItem()
{
// return new Datastore(); from somewhere
}
public List<object> GetList()
{
// return List<Datastore>(); from somewhere
}
}
class HostSystemHelper
{
public int HostSystemID { get; set; }
public string ClusterName {get; set;}
public object GetItem()
{
// return new HostSystem(); from somewhere
}
public List<object> GetList()
{
//return new List<HostSystem>(); from somewhere
}
}
But is the above a good idea or am I trying to fit a pattern in somewhere it doesn't belong?
EDIT: I've added some more overloaded methods to illustrate that my classes are complex and contain many methods, some overloaded many times according to different input params.
If I understand the concept correctly, a design like this is a really bad idea:
class DatastoreHelper
{
public string DatastoreName { get; set; }
public string DatastoreID { get; set; }
public object GetItem()
{
// return new Datastore(); from somewhere
}
public List<object> GetList()
{
// return List<Datastore>(); from somewhere
}
}
The reason is that getting results would now be a two-step process: first setting properties, then calling a method. This presents a whole array of problems:
Unintuitive (everyone is used to providing parameters as part of the method call)
Moves the parameter binding away from the call site (granted, this would probably mean "moves them to the previous LOC", but still)
It's no longer obvious which method uses which property values
Take an instance of this object and just add a few threads for instant fun
Suggestions:
Make both IGetObjects and GetObjectsManager generic so that you don't lose type safety. This loses you the ability to treat different managers polymorphically, but what is the point in that? Each manager will be in the end specialized for a specific type of object, and unless you know what that type is then you cannot really use the return value of the getter methods. So what do you stand to gain by being able to treat managers as "manager of unknown"?
Look into rewriting your GetX methods to accept an Expression<Func<T, bool>> instead of bare values. This way you can use lambda predicates which will make your code massively more flexible without really losing anything. For example:
helper.GetItem(i => i.DataStoreID == 42);
helper.GetList(i => i.DataStoreName.Contains("Foo"));
The first code samples look quite similar to the Repository Pattern. I think this is what are you trying to apply. The last sample is not good and Jon told you why. However, instead of reinventing the wheel, read a bit about the Repository (lots of questions about it on SO) because, if I understood correctly, this is what you really want.
About reuse, not many things and especially persistence interface are reusable. There is the Generic Repository Pattern (I consider it an anti-pattern) which tries to accomplish that but really, do all the application needs the same persistence interface?
As a general guideline, when you design an object, design it to fullfil the specific application needs, if it happens to be reused that's a bonus, but that's not a primary purpose of an object.
It is not a good idea. Based on these examples you would be better off with a generic interface for the varying return type and parameters of GetItem/GetList. Though honestly the prevalence of Managers, the use of something cas vague as GetItem in multiple places and trying to fit your solution into design patterns (rather than defining the solution in terms of the patterns) are huge code smells to me for the wider solution.

C# MongoDB: How to correctly map a domain object?

I recently started reading Evans' Domain-Driven design book and started a small sample project to get some experience in DDD. At the same time I wanted to learn more about MongoDB and started to replace my SQL EF4 repositories with MongoDB and the latest official C# driver.
Now this question is about MongoDB mapping. I see that it is pretty easy to map simple objects with public getters and setters - no pain there. But I have difficulties mapping domain entities without public setters. As I learnt, the only really clean approach to construct a valid entity is to pass the required parameters into the constructor. Consider the following example:
public class Transport : IEntity<Transport>
{
private readonly TransportID transportID;
private readonly PersonCapacity personCapacity;
public Transport(TransportID transportID,PersonCapacity personCapacity)
{
Validate.NotNull(personCapacity, "personCapacity is required");
Validate.NotNull(transportID, "transportID is required");
this.transportID = transportID;
this.personCapacity = personCapacity;
}
public virtual PersonCapacity PersonCapacity
{
get { return personCapacity; }
}
public virtual TransportID TransportID
{
get { return transportID; }
}
}
public class TransportID:IValueObject<TransportID>
{
private readonly string number;
#region Constr
public TransportID(string number)
{
Validate.NotNull(number);
this.number = number;
}
#endregion
public string IdString
{
get { return number; }
}
}
public class PersonCapacity:IValueObject<PersonCapacity>
{
private readonly int numberOfSeats;
#region Constr
public PersonCapacity(int numberOfSeats)
{
Validate.NotNull(numberOfSeats);
this.numberOfSeats = numberOfSeats;
}
#endregion
public int NumberOfSeats
{
get { return numberOfSeats; }
}
}
Obviously automapping does not work here. Now I can map those three classes by hand via BsonClassMaps and they will be stored just fine. The problem is, when I want to load them from the DB I have to load them as BsonDocuments, and parse them into my domain object. I tried lots of things but ultimately failed to get a clean solution. Do I really have to produce DTOs with public getters/setters for MongoDB and map those over to my domain objects? Maybe someone can give me some advice on this.
It is possible to serialize/deserialize classes where the properties are read-only. If you are trying to keep your domain objects persistance ignorant, you won't want to use BsonAttributes to guide the serialization, and as you pointed out AutoMapping requires read/write properties, so you would have to register the class maps yourself. For example, the class:
public class C {
private ObjectId id;
private int x;
public C(ObjectId id, int x) {
this.id = id;
this.x = x;
}
public ObjectId Id { get { return id; } }
public int X { get { return x; } }
}
Can be mapped using the following initialization code:
BsonClassMap.RegisterClassMap<C>(cm => {
cm.MapIdField("id");
cm.MapField("x");
});
Note that the private fields cannot be readonly. Note also that deserialization bypasses your constructor and directly initializes the private fields (.NET serialization works this way also).
Here's a full sample program that tests this:
http://www.pastie.org/1822994
I'd go with parsing the BSON documents and move the parsing logic to a factory.
First define a factory base class, which contains a builder class. The builder class will act as the DTO, but with additional validation of the values before constructing the domain object.
public class TransportFactory<TSource>
{
public Transport Create(TSource source)
{
return Create(source, new TransportBuilder());
}
protected abstract Transport Create(TSource source, TransportBuilder builder);
protected class TransportBuilder
{
private TransportId transportId;
private PersonCapacity personCapacity;
internal TransportBuilder()
{
}
public TransportBuilder WithTransportId(TransportId value)
{
this.transportId = value;
return this;
}
public TransportBuilder WithPersonCapacity(PersonCapacity value)
{
this.personCapacity = value;
return this;
}
public Transport Build()
{
// TODO: Validate the builder's fields before constructing.
return new Transport(this.transportId, this.personCapacity);
}
}
}
Now, create a factory subclass in your repository. This factory will construct domain objects from the BSON documents.
public class TransportRepository
{
public Transport GetMostPopularTransport()
{
// Query MongoDB for the BSON document.
BsonDocument transportDocument = mongo.Query(...);
return TransportFactory.Instance.Create(transportDocument);
}
private class TransportFactory : TransportFactory<BsonDocument>
{
public static readonly TransportFactory Instance = new TransportFactory();
protected override Transport Create(BsonDocument source, TransportBuilder builder)
{
return builder
.WithTransportId(new TransportId(source.GetString("transportId")))
.WithPersonCapacity(new PersonCapacity(source.GetInt("personCapacity")))
.Build();
}
}
}
The advantages of this approach:
The builder is responsible for building the domain object. This allows you to move some trivial validation out of the domain object, especially if the domain object doesn't expose any public constructors.
The factory is responsible for parsing the source data.
The domain object can focus on business rules. It's not bothered with parsing or trivial validation.
The abstract factory class defines a generic contract, which can be implemented for each type of source data you need. For example, if you need to interface with a web service that returns XML, you just create a new factory subclass:
public class TransportWebServiceWrapper
{
private class TransportFactory : TransportFactory<XDocument>
{
protected override Transport Create(XDocument source, TransportBuilder builder)
{
// Construct domain object from XML.
}
}
}
The parsing logic of the source data is close to where the data originates, i.e. the parsing of BSON documents is in the repository, the parsing of XML is in the web service wrapper. This keeps related logic grouped together.
Some disadvantages:
I haven't tried this approach in large and complex projects yet, only in small-scale projects. There may be some difficulties in some scenarios I haven't encountered yet.
It's quite some code for something seemingly simple. Especially the builders can grow quite large. You can reduce the amount of code in the builders by converting all the WithXxx() methods to simple properties.
A better approach to handling this now is using MapCreator (which was possibly added after most of these answers were written).
e.g. I have a class called Time with three readonly properties: Hour, Minute and Second. Here's how I get it to store those three values in the database and to construct new Time objects during deserialization.
BsonClassMap.RegisterClassMap<Time>(cm =>
{
cm.AutoMap();
cm.MapCreator(p => new Time(p.Hour, p.Minute, p.Second));
cm.MapProperty(p => p.Hour);
cm.MapProperty(p => p.Minute);
cm.MapProperty(p => p.Second);
}
Niels has an interesting solution but I propose a much different approach:
Simplify your data model.
I say this because you are trying to convert RDBMS style entities to MongoDB and it doesnt map over very well, as you have found.
One of the most important things to think about when using any NoSQL solution is your data model. You need to free your mind of much of what you know about SQL and relationships and think more about embedded documents.
And remember, MongoDB is not the right answer for every problem so try not to force it to be. The examples you are following may work great with standard SQL servers but dont kill yourself trying to figure out how to make them work with MongoDB - they probably dont. Instead, I think a good excercise would be trying to figure out the correct way to model the example data with MongoDB.
Consider NoRM, an open-source ORM for MongoDB in C#.
Here are some links:
http://www.codevoyeur.com/Articles/20/A-NoRM-MongoDB-Repository-Base-Class.aspx
http://lukencode.com/2010/07/09/getting-started-with-mongodb-and-norm/
https://github.com/atheken/NoRM (download)

How to make a Generic Repository?

I am wondering if anyone has any good tutorials(or maybe even a library that is already made and well documented) on making a generic repository.
I am using currently linq to sql but it might change so I don't know if you can make a generic repository that would take little to no changes if I would say switch to entity framework.
Thanks
I think I should also add why I want a generic repository. The reason is in my database I have like corporate tables(users who's subscriptions are paid by someone else) and individual tables(people who find my site through google or whatever and pay for their own subscription)
But I will have 2 very similar tables. For instance I have 2 settings tables one for corporate users and one for the individuals.
Now since they are 2 different tables I need 2 different insert methods as I am inserting it into 2 different tables and at this current time only one field is different(that is the PK).
So now I need all these duplicate methods and I don't want that. Maybe what I have in my database is could be considered as a design flaw(and maybe it is) but one of the reasons behind this was if needed I can break up my database into 2 different databases very easy and I am not going to change my design anytime soon.
Here is my answer to another question of the same type. Hope it helps:
Advantage of creating a generic repository vs. specific repository for each object?
Edit:
It sounds like you want to treat two concrete types as one logical type. To do that, first define the logical type:
public interface ISubscription
{
// ...
}
Then, define the concrete types as part of your data model (interfaces would be implemented in another partial class):
[Table("CorporateSubscription")]
public partial class CorporateSubscription : ISubscription
{
}
[Table("IndividualSubscription")]
public partial class IndividualSubscription : ISubscription
{
}
Next, define the repository which operates on the logical type:
public interface ISubscriptionRepository
{
CorporateSubscription GetCorporate(string key);
IndividualSubscription GetIndividual(int userId);
IEnumerable<ISubscription> ListAll();
IEnumerable<CorporateSubscription> ListCorporate();
IEnumerable<IndividualSubscription> ListIndividual();
void Insert(ISubscription subscription);
}
Finally, implement the interface by using both tables:
public class SubscriptionRepository : ISubscriptionRepository
{
private readonly YourDataContext _dataContext;
public SubscriptionRepository(YourDataContext dataContext)
{
_dataContext = dataContext;
}
#region ISubscriptionRepository
public CorporateSubscription GetCorporate(string key)
{
return _dataContext.CorporateSubscriptions.Where(c => c.Key == key).FirstOrDefault();
}
public IndividualSubscription GetIndividual(int userId)
{
return _dataContext.IndividualSubscriptions.Where(i => i.UserId == userId).FirstOrDefault();
}
public IEnumerable<ISubscription> ListAll()
{
return ListCorporate()
.Cast<ISubscription>()
.Concat(ListIndividual().Cast<ISubscription>());
}
public IEnumerable<CorporateSubscription> ListCorporate()
{
return _dataContext.CorporateSubscriptions;
}
public IEnumerable<IndividualSubscription> ListIndividual()
{
return _dataContext.IndividualSubscriptions;
}
public void Insert(ISubscription subscription)
{
if(subscription is CorporateSubscription)
{
_dataContext.CorporateSubscriptions.InsertOnCommit((CorporateSubscription) subscription);
}
else if(subscription is IndividualSubscription)
{
_dataContext.IndividualSubscriptions.InsertOnCommit((IndividualSubscription) subscription);
}
else
{
// Forgive me, Liskov
throw new ArgumentException(
"Only corporate and individual subscriptions are supported",
"subscription");
}
}
#endregion
}
Here is an example of an insert. Don't get too wrapped up in the presenter class; I just needed a situation in which subscriptions would be created based on a flag:
public class CreateSubscriptionPresenter
{
private readonly ICreateSubscriptionView _view;
private readonly ISubscriptionRepository _subscriptions;
public CreateSubscriptionPresenter(
ICreateSubscriptionView view,
ISubscriptionRepository subscriptions)
{
_view = view;
_subscriptions = subscriptions;
}
public void Submit()
{
ISubscription subscription;
if(_view.IsCorporate)
{
subscription = new CorporateSubscription();
}
else
{
subscription = new IndividualSubscription();
}
subscription.Notes = _view.Notes;
_subscriptions.Insert(subscription);
}
}
Great Linq to Sql resources:
A t4 template that by generates exactly what is created by default, but can be fully customised.
http://l2st4.codeplex.com/
Using Linq to Sql for a multi tier application. It has a GenericObjectDataSource which I have found very handy
http://multitierlinqtosql.codeplex.com
Search all properties of an IQueryable with one single search
http://naspinski.codeplex.com/

How to refactor this?

I'm struggling with a small issue with regard to how I go about refactoring this to a decent pattern.
public class DocumentLibrary
{
private IFileSystem fileSystem;
private IDocumentLibraryUser user;
public DocumentLibrary(IDocumentLibraryUser user) : this(user, FileSystemFrom(user)) { }
public DocumentLibrary(IDocumentLibraryUser user, IFileSystem fileSystem)
{
this.user = user;
this.fileSystem = fileSystem;
}
public void Create(IWorkerDocument document)
{
document.SaveTo(fileSystem);
}
public IWorkerDocument AttemptContractRetrieval()
{
return new Contract(fileSystem, user);
}
public IWorkerDocument AttemptAssignmentRetrieval()
{
return new Assignment(fileSystem, user);
}
private static IFileSystem FileSystemFrom(IDocumentLibraryUser user)
{
var userLibraryDirectory = new DirectoryInfo("/DocLib/" + EnvironmentName() + "/" + user.Id);
return new FileSystem(userLibraryDirectory);
}
private static string EnvironmentName()
{
using (var edmxContext = new Entities())
{
return (from setting in edmxContext.EnvironmentSettings
where setting.Name == "EnvironmentName"
select setting.Value).First();
}
}
}
I have two types of worker documents, but I can't seem to easily refactor the two methods above (AttemptContractRetrieval and AttemptAssignmentRetrieval) to a decent form.
Any help would be much appreciated.
Regards,
Jim.
Personnally, I would consider either a factory pattern using factory methods or a builder pattern.
Good use of the factory pattern can be seen in the Enterprise Library solution e.g:
Database.CreateDatabase();
I would say this would be the most straight forward to integrate.
If you chose the Builder pattern, with a requirement to create more complex objects, then you can separate out the creation of complex objects into a series of build commands e.g:
vehicleBuilder.BuildFrame();
vehicleBuilder.BuildEngine();
vehicleBuilder.BuildWheels();
vehicleBuilder.BuildDoors();
Then within these methods, given your chosen implementation, you can add your complexity but make the method calls and construction quite straight forward.
If you haven't come across it, http://www.dofactory.com is a good place to go.
I can see two aspects to this:
What do I need to do to add a new IWorkerDocument class? Adding new methods seems heavyweight.
What code does the caller need in order to create an IWorkerDocument? Right now the responsibility for calling the correct method lies with the caller, hence it's quite likely that the caller also needs to change each time there is a new IWorkerDocument implementor.
The extent of possible refactoring very much depends upon the answer to 2. Sometimes the caller just has to know what they're making, and in which case the code you have is pretty much all you can do. In other cases you have some "WorkerDefinition" stuff, perhaps in the form of a set of Properties, or a name that can be looked up in a registry. In which case the caller wants an api of the form
makeMeAWorker(WorkerDefinition def)
on a Factory. Now the caller has no idea what he's asking for, delegates the whole thing to the factory. So the client's world need not change as you add new Worker types.
The Factory can be made extensible by some form of registration scheme or dynamic configuration scheme. We can inject new types into the factory by many different mechanisms.
I think it depends on what other responsibilities the class has that contains those methods. Design patterns are structural constructs. Here we infer that there is a class
class Retriever
{
...
public IWorkerDocument AttemptContractRetrieval()
{
}
public IWorkerDocument AttemptAssignmentRetrieval()
{
}
}
The client code is already deciding whether to call AttemptContractRetrieval(), or AttemptAssignmentRetrieval, so maybe polymorphism is in order.
class ContractRetriever
{
public IWorkerDocument AttemptRetrieval()
{
}
}
class AssignmentRetriever
{
public IWorkerDocument AttemptRetrieval()
{
}
}
You can make an abstract Retriever class and have these as descendents of that. This will force the derived classes to have an AttemptRetrieval() method.
If you execute similar actions on the retrieved documents, you may consider having Contract and Assignment classes instead of ContractRetriever and AssignmentRetriever. Then you can put common actions in their parent.
In short, a lot of the answer here lies in the unstated context of the problem.
For interested people, I have gone for a factory method.
public IWorkerDocument AttemptRetrieval<T>() where T : IWorkerDocument
{
return WorkerDocument.Create<T>(fileSystem, user);
}
calls
public static IWorkerDocument Create<T>(IFileSystem fileSystem, IDocumentLibraryUser user) where T : IWorkerDocument
{
var documentType = typeof(T);
if (documentType == typeof(Contract))
return new Contract(fileSystem, user);
if (documentType == typeof(Assignment))
return new Assignment(fileSystem, user);
throw new Exception("Invalid Document Type");
}
It's a little messy, so does anyone have any suggestions to clean the actual factory method up?
what about this:
public IWorkerDocument AttemptRetrieval<T>() where T:new, IWorkerDocument
{
return new T {FileSystem=fileSystem,User=user}
}
Out of the top of my head, so may contain a blatant error ;-)
Are you looking for the Abstract Factory pattern? The declared intent in 'Design Patterns' is "Provide an interface for creating families of related or dependent objects without specifying their concrete classes."
http://en.wikipedia.org/wiki/Abstract_factory

Categories