Before this is marked as duplicate I have looked around to find an answer for my question, but my scenario is a little more specific than other similar questions found on SO and I don't think anwers like "it's a bad practice" apply.
I am working on some design choices for modeling the domain following the DDD approach with Entity Framework, and I am interested in a way to inject dependencies into Entities. To be precise the only dependencies I consider worth injecting are factories for domain objects that belong to the aggregate root I am working with or wrappers around static classes like the one below:
public class CurrentTimeProvider : ITimeProvider
{
public DateTime GetTime()
{
return DateTime.Now();
}
}
The purpose of the wrapper is to make unit testing easier and I am not a fan of the double dispatch pattern for this case as it breaks encapsulation.
Sample entity:
public class ActivationToken
{
protected ITimeProvider TimeProvider;
public ActivationToken(ITimeProvider timeProvider)
{
TimeProvider = timeProvider;
}
public virtual DateTime? ConsumedTime { get; protected set; }
public virtual void Consume()
{
ConsumedTime = TimeProvider.GetTime();
}
}
So my question is how do I get Entity Framework to provide my dependency when creating the instance?
Part of the reason this is difficult is that conceptually, you are mixing up injectibles and newables.
See http://misko.hevery.com/2008/09/30/to-new-or-not-to-new/ for an explanation of the difference.
Entities in DDD fit into the 'newable' category. Application services, domain services, repositories etc. are injectible.
An alternative approach for your example is to use 'method injection' and to pass in ITimeProvider directly into the Consume method:
public class ActivationToken
{
public ActivationToken()
{
}
public virtual DateTime? ConsumedTime { get; protected set; }
public virtual void Consume(ITimeProvider timeProvider)
{
ConsumedTime = timeProvider.GetTime();
}
}
This still allows unit testing with a mock time provider, and ensures that the entities fields are only about the state of the entity. You can obtain an instance of the ITimeProvider by injecting it into the application service/use case that will call the Consume method.
I think the simplest way is to avoid constructor injection and register a global Service Locator that you can access from your no-arg constructor, eg:
public class ActivationToken
{
protected ITimeProvider TimeProvider;
public ActivationToken()
{
TimeProvider = ServiceLocator.Instance.GetService<ITimeProvider>();
}
public virtual DateTime? ConsumedTime { get; protected set; }
public virtual void Consume()
{
ConsumedTime = TimeProvider.GetTime();
}
}
Related
I'm building a password generator. I'm trying to apply the Dependency Inversion Principle (DIP) but so far my solution still seems to be coupled with concrete data.
How do I decouple the PasswordGenerator? So I don't have to pass to it
new PasswordRequirementsRepository(new PasswordRequirements{[properties assigned here]})
and I can inject an interface instead which will be used by IoC Container?
How can I pass in the data assigned to PasswordRequirements properties to the PasswordGenerator without creating an instance of PasswordRequirementsRepository?
I'm struggling when passing different sets of password requirements because in PasswordGenerator I have to pass a concrete instance of PasswordRequirementsRepository instead of interface. I guess what I'm trying to achieve is to decouple PasswordGenerator from the concrete set of password requirements.
IPasswordRequirementsRepository.cs
public interface IPasswordRequirementsRepository
{
PasswordRequirements GetPasswordRequirements();
}
PasswordRequirementsRepository.cs
public class PasswordRequirementsRepository : IPasswordRequirementsRepository
{
private readonly PasswordRequirements _requirements;
public PasswordRequirementsRepository(PasswordRequirements requirements)
{
_requirements = requirements;
}
public PasswordRequirements GetPasswordRequirements()
{
return _requirements;
}
}
IPasswordGenerator.cs
public interface IPasswordGenerator
{
string GeneratePassword();
}
PasswordGenerator.cs
public class PasswordGenerator : IPasswordGenerator
{
private readonly IPasswordRequirementsRepository _repository;
public PasswordGenerator(IPasswordRequirementsRepository repository)
{
_repository = repository;
}
public string GeneratePassword()
{
PasswordRequirements requirements = _repository.GetPasswordRequirements();
[password generation logic here]
}
}
PasswordRequirements.cs
public class PasswordRequirements
{
public int MaxLength { get; set; }
public int NoUpper { get; set; }
public int NoLower { get; set; }
public int NoNumeric { get; set; }
public int NoSpecial { get; set; }
}
How do I decouple the PasswordGenerator? So I don't have to pass to it and I can inject an interface instead which will be used by IoC Container?
1st - Derive an interface:
public class IPasswordRequirements
{
int MaxLength { get; }
int NoUpper { get; }
int NoLower { get; }
int NoNumeric { get; }
int NoSpecial { get; }
}
2nd - Inherit from interface:
public class PasswordRequirements : IPasswordRequirements
{
public int MaxLength { get; set; }
public int NoUpper { get; set; }
public int NoLower { get; set; }
public int NoNumeric { get; set; }
public int NoSpecial { get; set; }
}
3rd - Update constructor:
public class PasswordGenerator : IPasswordGenerator
{
public PasswordGenerator(IPasswordRequirements passwordRequirements)
{
}
That's it.
Don't use a repository here
My fear is that your understanding of a repository and DI infer some time of requirement to always be used together. What I believe your lacking is the code that instantiates dependencies. While a repository may at it's core provide that as a bases of it's pattern, it isn't the correct choice here, because of two reasons; first you aren't storing the items in the repository (that is there is no tier virtual or physical abstraction to wrap the repository around) and secondly you aren't providing generic access to a wide variety of types, just a single one.
At it's core the only thing a repository needs to be useful is a configuration/object to pass objects.. to some other tier (SQL, File system, Web API). A repository is not required in all instances to know anything about how objects are created.
Choose a framework that fits your need
Instead, what you need is a framework built at it's core around DI; object creation and disposal, and having an interface/configuration in which to configure the framework so it can be aware of dependencies to assist in the creation of dependent objects. There are three that come to mind AutoFac, Ninject and Unity. In each of these case, you are in some way, required to configure each type and use it's pattern to create objects. In many cases these Frameworks can even be full featured replacements with other Microsoft Frameworks (MVC for example, has it's own way to instantiate objects, but can be replace with other DI Frameworks). In no way are these frameworks required to know configuration on how to pass these objects to other tiers. It may do so simply by configuration as a by-product, but at it's core that's not what is configured.
For example with Autofac, first you create builder which is basically a fancy way to create a configuration:
var builder = new ContainerBuilder()
Then you register your types:
builder.RegisterType<PasswordRequirements>.As<IPasswordRequirements>();
Create a Container which manages objects: from their instantiation to their configuration.
var container = builder.Build();
Create a scope which defines the duration of an objects lifetime.
using (var scope = new BeginLifetimeScope())
{
// all objects created by scope which be disposed when the scope is diposed.
var passwordRequirements = scope.Resolve<IPasswordRequirements>();
}
By default passwordRequirements will be a new PasswordRequirements(). From there you simply build out your necessary dependency requirements and let the framework handle the rest.
Crux of the issue related to Dependency Inversion
On creating the instance of the PasswordGenerator. which inject, IPasswordRequirementsRepository, in current design there's a limitation of passing the concrete instance of PasswordRequirements, which shall be avoided for true Dependency inversion design.
Following are the possible solutions:
Create an interface or preferably an abstract class for the PasswordRequirements, which can be overridden and can be injected on the need basis, which will be automatically injected when IPasswordRequirementsRepository is injected in the PasswordGenerator
Let's consider the abstract class:
public abstract class BasePasswordRequirements
{
public abstract int MaxLength { get; set; }
public abstract int NoUpper { get; set; }
public abstract int NoLower { get; set; }
public abstract int NoNumeric { get; set; }
public abstract int NoSpecial { get; set; }
}
public class PasswordRequirements : BasePasswordRequirements
{
public override int MaxLength { get; set; }
public override int NoUpper { get; set; }
public override int NoLower { get; set; }
public override int NoNumeric { get; set; }
public override int NoSpecial { get; set; }
}
Using Ninject DI container Binding would be as follows, along with named binding:
Kernel.Bind<IPasswordRequirementsRepository>().To<PasswordRequirementsRepository>()
Kernel.Bind<BasePasswordRequirements>().To<PasswordRequirements>()
PasswordRequirementsRepository will be as follows:
public class PasswordRequirementsRepository : IPasswordRequirementsRepository
{
private readonly BasePasswordRequirements Requirements{get;}
public PasswordRequirementsRepository(BasePasswordRequirements requirements)
{
Requirements = requirements;
}
public BasePasswordRequirements GetPasswordRequirements()
{
return Requirements;
}
}
Another option would be constructor Injection, in that case PasswordRequirements, may not need a Base class or interface, in that case binding would be like:
Kernel.Bind<IPasswordRequirementsRepository>().To<PasswordRequirementsRepository>()
.WithConstructorArgument("requirements", new
PasswordRequirements { .... });
This would call the correct constructor, with relevant values filled in
You may also consider combination of both approached 1 and 2 , where you create a base class / interface for PasswordRequirements and also constructor injection.
For various versions of PasswordRequirements, that you may want to inject consider named binding, following shall be example, instead of:
public class PasswordRequirementsRepository : IPasswordRequirementsRepository
{
private readonly Func<string,BasePasswordRequirements> RequirementsFunc{get;}
public PasswordRequirementsRepository(Func<string,BasePasswordRequirements> requirementsFunc)
{
RequirementsFunc = requirementsFunc;
}
public BasePasswordRequirements GetPasswordRequirements(string name="Version1")
{
return requirementsFunc(name);
}
}
Ninject Binding would be as follows
Kernel.Bind<Func<string,BasePasswordRequirements>>()
.ToMethod(context => name => context.Kernel
.Get<BasePasswordRequirements>(name);
);
Bind<BasePasswordRequirements>().To<PasswordRequirements>().Named("Version1");
Bind<BasePasswordRequirements>().To<AnotherPasswordRequirements>().Named("Version2");
Here the Name for Binding can be passed at the run-time to tweak object that will be injected and thus change the behavior by run-time, thus achieving dependency inversion by using a DI framework like Ninject, which lot of flexible options
Based on the code snippet in your question, the implementation of PasswordGenerator is decoupled from the implementation of the IPasswordRequirementsRepository as it is the interface that is given as constructor argument and not a specific implementation.
To decouple the PasswordRequirementsRepository from a specific implementation of the PasswordRequirements you can do one of two things.
Introduce an interface IPasswordRequirements.
Make PasswordRequirements abstract.
Either approach will decouple the implementation of PasswordRequirementsRepository from the implementation of PasswordRequirements.
DI container
How do I decouple the PasswordGenerator? So I don't have to pass to it
new PasswordRequirementsRepository(new PasswordRequirements{[properties assigned here]})
and I can inject an interface instead which will be used by IoC Container? How can I pass in the data assigned to PasswordRequirements properties to the PasswordGenerator without creating an instance of PasswordRequirementsRepository?
I believe that this part of the question builds on a misunderstanding of the role of the DI container. When building your container you will register all the Classes/Interfaces that is needed in your system. This could look something like the following:
Register<IPasswordRequirements>().To<PasswordRequirements>();
Register<IPasswordRequirementsRepository>().To<PasswordRequirementsRepository>();
Register<IPasswordGenerator>().To<PasswordGenerator>();
After registering everything you can ask the container to provide you with an instance of an interface. In your case, this would be an instance of IPasswordGenerator. The request typically looks a something like this:
var passwordGenerator = contain.Resolve<IPasswordGenerator>();
Normally you only request the topmost component of your program, as the DI container knows what is needed to instantiate every class the component depends on. You would not create a new instance of PasswordGenerator by manually resolving the dependencies and the inject these into the constructor. This approach counteracts the purpose of the DI container.
One option might be to use generics to abstract out the different types of password requirements you might use, and pass the options through the GeneratePassword method since that's really a parameter to how you generate the password. I.E.
interface IPasswordGenerator<TPasswordRequirements>
{
string GeneratePassword(TPasswordRequirements reqs);
}
interface IPasswordRequirementRepository<TPasswordRequirements>
{
TPasswordRequirements GetPasswordRequirements();
}
Implemented by
class DefaultPasswordReqs
{
public int MaxLength { get; set; }
// ...
}
class DefaultPasswordGenerator : IPasswordGenerator<DefaultPasswordReqs>
{
public string GeneratePassword(DefaultPasswordReqs reqs)
{
// ... logic specific to DefaultPasswordReqs
}
}
class InMemoryPasswordRequiremntsRepository<TPasswordRequirements> :
IPasswordRequirementRepository<TPasswordRequirements>
{
private readonly TPasswordRequirements _reqs;
public InMemoryPasswordRequiremntsRepository(TPasswordRequirements reqs)
{
_reqs = reqs;
}
public TPasswordRequirements GetPasswordRequirements()
{
return _reqs;
}
}
And then in whatever code depends on the password generator, have it take a dependency which has the specifc type of password requirements it will use and read the requirements and use those requirements to generate the password.
var requirements = _passwordRequiremntsRepository.GetPasswordRequirements();
var password = _passwordGenerator.GeneratePassword(requirements);
I have a class similar to the below (C#):
public class Product {
public int ID {get;set;}
public string Name {get;set;}
public double Price {get;set;}
public void Save() {
string sql = "INSERT INTO Product.....";
Database.Execute(sql);
}
public void Delete() {
string sql = "DELETE Product WHERE.....";
Database.Execute(sql);
}
}
My main concern is that the code above violates SOLID principles, since it takes responsibility for creating and deleting itself.
Perhaps these Save and Delete methods should be placed somewhere outside the Product entity (Factory/Repository maybe?).
I would introduce your model entity, a command and query pattern and a database layer or repository.
Your model is your Product and this object should be a plain object:
public class Product : IEntity {
public int ID { get; set; }
public string Name { get; set; }
public double Price { get; set; }
}
Next I would create a command and query interface for working with this entity:
public interface ICommand {} // Marker interface
public interface IQuery<TResult> {} // Marker interface
Next define the handlers for ICommand and IQuery:
public interface IHandleQuery<TQuery, TResult> where TQuery : IQuery<TResult>
{
TResult Handle(TQuery query);
}
public interface IHandleCommand<TCommand> where TCommand : ICommand
{
void Handle(TCommand command);
}
Now you have a clear indication and separation of your write (command) and read (query) sides.
This means we can create a command and its handler for saving your Product like:
public class SaveProduct : ICommand
{
public string Name { get; private set; }
public double Price { get; private set; }
public SaveProduct(string name, double price)
{
Name = name;
Price = price;
}
}
public class HandleSaveProduct : IHandleCommand<SaveProduct>
{
private readonly IRepository<Product> _productRepository;
public HandleSaveProduct(IRepository<Product> productRepository)
{
_productRepository = productRepository;
}
public void Handle(SaveProduct command)
{
var product = new Product {
Name = command.Name,
Price = command.Price
};
_productRepository.Save(product);
}
}
In the above we have defined an repository for handling this entity,
you can however depend directly on your database context here and do
the queries/commands to it or you can implement the repository pattern
using an GenericRepository<TEntity> : IRepository<TEntity> or just
the separate product repository:
public interface IEntity { } // Marker interface
public interface IRepository<TEntity> where TEntity : IEntity
{
TEntity Get(object primaryKey);
void Save(TEntity entity); // should handle both new and updating entities
void Delete(TEntity entity);
}
public class ProductRepository : IRepository<Product>
{
public Product Get(object primaryKey)
{
// Database method for getting Product
}
public void Save(Product entity)
{
// Database method for saving Product
}
public void Delete(Product entity)
{
// Database method for deleting Product
}
}
You should never return your Product entity to your UI, but use a view model, e.g:
public class ProductViewModel {
public int ID { get; set; }
public string Name { get; set; }
public double Price { get; set; }
public DateTime Whatever { get; set; }
}
public class GetProductById : IQuery<ProductViewModel>
{
public int Id { get; private set; }
public GetProductById(int id)
{
Id = id;
}
}
public class HandleGetProductById : IHandleQuery<GetProductById, ProductViewModel>
{
private readonly IRepository<Product> _productRepository;
public HandleGetProductById(IRepository<Product> productRepository)
{
_productRepository = productRepository;
}
public ProductViewModel Handle(GetProductById query)
{
var product = _productRepository.Get(query.Id);
return product.Select(x => new ProductViewModel {
Name = x.Name,
Price = x.Price;
});
}
}
Please note this is written in notepad, might not compile 100%, but you should get the idea on how the separation of the various components should be in order to follow SOLID. :-)
I believe the Facade pattern will do just fine in your case. The Facade pattern is also known as Service Layer.
In your case you will basically have a service(a class) which will have all the methods you need. Your service should look something like this.
class ProductService
{
public void Save(Product product)
{
// SAVE THE PRODUCT
}
public void Delete(Product product)
{
// DELETE PRODUCT
}
}
You want to inject your class where you want to save or delete products. This way all the work you have to do will be in a separate class and your code will become much cleaner.
It's also a good idea to have all those insert and delete statemenets in stored procedures.
You seem to want some sort of Repository like contract. You've already alluded to it in your [kind of] question. The link is for reference - I'm not suggesting you implement one. Why?
Because like #Igor said, if you're using an ORM then you'll get this contract for free. For example, NHibernate has an ISession with Query<T>(), Save(), Delete(), etc methods. This is all you need.
Nearly every project I've worked on where some abstraction over this "infrastructure" ORM contract is used (service/repository/etc), the said abstraction is weak and only serves to create more code to maintain and a higher risk of tech debt and bugs.
Take the pragmatic approach:
Don't reinvent the wheel by creating a Repository/ORM abstraction of your own with ADO.NET calls inside. Use a solid ORM like Fluent NHibernate which makes mapping simple and interacting with the data easy (other perfectly sound alternatives might be Entity Framework, etc). If that's too much party for you, try something really simple like Dapper - it's a very lightweight ORM which maps to your models like freaking magic and you can still write all your own SQL. You'll get your ORM contract interface to use, which I believe is what you're asking for here, and you can get on with building out your app, rather than pondering about over engineering.
Keep stuff simple by using your ORM contract in your controllers ('controllers' doesn't have to be MVC Controllers, it can be whatever the UI entry point for your app is. Remember: avoid unnecessary abstractions). Here are some simple examples.
Folks want to keep things DRY, but the bizarre addiction developers have to #reusingallthethings means they often have Repositories or Services which wrap a perfectly fine ORM contract call and often only have one or two usages. Forget about reuse! Use the Rule of Three and start by having your queries, save and delete logic in your controllers and only extract reusable code when you know you need to.
I know these examples are
trivial,
but just imagine you needed to return some data and the query
required some long linq expression or complex select with joins. Now imagine you needed this same query in a few places (it happens. Not often, but you will have some) - copy and paste it! Yes that's right; you can't believe I said it but I did. Leave that identical 10 lines copied and pasted in 2, 3 or 4 places in your code. It's totally ok. No one will die. You don't need a query object or a Repository method as long as the linq expression itself (GetTop15TransactionsWithoutFeesExcludingCreditsGroupByDayRecentAtTop() anyone?).
HTH.
So I'm using interfaces more these days. But I am coming across a brick wall this time.
Just for context only let me show you the RESTful WCF contract here that I designed to show you how I'm using IPaymentRequest:
[ServiceContract]
public interface IPaymentService
{
[WebInvoke(Method = "POST", UriTemplate = "/PreAuthorization")]
PreAuthorizeResponse SendTransaction(PreAuthorizeRequest request);
[WebInvoke(Method = "POST", UriTemplate = "/Capture")]
CaptureResponse SendTransaction(CaptureRequest captureRequest);
... and so on
}
The implementation of the Service Contract for example has some methods that look like this:
public PreAuthorizeResponse SendTransaction(PreAuthorizeRequest request)
{
.....
Processor.SetSettings(request);
}
(Note/disclaimer on clean code principals. I have better names for stuff like the name SetSettings() but for privacy I've named stuff more simple such as "SetSettings" and "Process" for this Stack post. In reality I have what kind of processor in its class name so just FYI).
Second, let me make you aware that I have a Processor class that is basically kinda like a utility class to do some things such as send the request fields to an outside REST API. And in this class one example of another method I'm setting up is a SetSettings method that I'll set some stuff based on the type of request that comes in. Mostly, I'm going to get the stuff I need from its Transaction property.
public class Processor
{
private void SetSettings(IPaymentRequest request)
{
var someValue = request.Transaction.SomeProperty1;
...
}
}
Now here's what the IPaymentRequest looks like:
public interface IPaymentRequest
{
string Token { get; set; }
int ClientID { get; set; }
}
Now here are a couple examples of my domain models (the Models my Service Contract expects to be sent in from client requests) that implement IPaymentRequest:
public class PreAuthorizeRequest : IPaymentRequest
{
public string Token { get; set; }
public int ClientID { get; set; }
public int Amount { get; set; }
public PreAuthTransaction Transaction { get; set; }
}
public class CaptureRequest : IPaymentRequest
{
public string Token { get; set; }
public int ClientID { get; set; }
public int BankID { get; set; }
public CaptureTransaction Transaction { get; set; }
}
I'm using IPaymentRequest throughout my WCF service (it's the type that's expected to be sent into my payment service's method contracts) and using these interfaces elsewhere in my service to make some good reuse of methods that these requests can flow through such as SendRequest(IPaymentRequest request), and so on.
Here is the dilema/problem I have:
In methods where I want to reuse the logic for any kind of request that comes in, I end up having to check for what type it is incoming to my methods sometimes in my processor class. So I am having to create a bunch of messy if statements in order to determine and cast the incoming ITransaction in order to start using it in my utility mehtods here.
So lets continue more so I can explain more about my First method SetSettings()
Notice that I need values from the transaction object in the request and to be able to work with properties in that TYPE of request.
Now lets take a look at the CaptureTransaction object for example for a CaptureRequest
public class CaptureTransaction : ITransaction
{
public string Reference { get; set; }
public decimal Amount { get; set; }
public string CurrencyCode { get; set; }
public CreditCard CustomerCreditCard { get; set; }
}
So as you can see, for each Request Type I have a related concrete Transaction Type that implements ITransaction and holds info that the transaction needs to send over to an external API.
Note: All requests WILL always have a transaction (ITransaction) so I thought it'd be therefore a good idea to maybe throw ITransaction in my IPaymentRequest so something like this:
public interface IPaymentRequest
{
string Token { get; set; }
int ClientID { get; set; }
ITransaction Transaction {get; set; }
}
And here is ITransaction. Every request that comes into our service will require a currency now and in the future so this field was a good candidate/reason to use an Interface:
public interface ITransaction
{
string CurrencyCode { get; set; }
}
So adding that to my IPaymentRequest now requires me to change the Property Name in my Custom Types to "Transaction", for example:
public class CaptureRequest : IPaymentRequest
{
public string Token { get; set; }
public int ClientID { get; set; }
public int BankID { get; set; }
public ITransaction Transaction { get; set; }
}
I thought ok fine.
But now if I try to work with Transactions in my utility method, since it's an Interface variable, it has no idea what type of Transaction it is. So I end up having to cast it before I can use it:
private void SetSettings(IPaymentRequest request)
{
ITransaction transaction;
if (request is CaptureRequest)
transaction = request.Transaction as CaptureTransaction;
if (request is PreAuthorizeRequest)
transaction = request.Transaction as PreAuthorizeTransaction;
... etc.
var someValue = request.Transaction.Some1;
...carry on and use SomeProperty1elsewhere in this method for whatever reason
}
IMO it just feels strongly like huge code smell. So obviously I am not doing something right or I don't yet know something about Interfaces that I should know...that allows me to use them better here or without so much casting. And just too much casting IMO is bad, performance-wise.
Maybe this is a good case to use Generics instead of interface parameters in methods I want to create for reuse across different types of Concrete Request types (Capture, PreAuth, Void yada yada)?
The whole point here is I want to be able to specify interface params in some methods to make them DRY (don't repeat yourself) / reusable...and then use the concrete type that came in via polymorphism and work with the request instance.
If every request has a transaction, then this is the right way to go:
interface IPaymentRequest
{
string Token { get; set; }
int ClientID { get; set; }
ITransaction Transaction { get; set; }
}
Obviously, to process the custom request, you'll need a custom processor:
class Processor
{
protected virtual void OnSetSettings(IPaymentRequest request)
{
}
private void SetSettings(IPaymentRequest request)
{
// do the common stuff
// ...
// set custom settings
OnSetSettings(request);
}
}
class PreAuthorizeRequestProcessor : Processor
{
protected override void OnSetSettings(IPaymentRequest request)
{
base.OnSetSettings(request);
// set custom settings here
var customRequest = (PreAuthorizeRequest)request;
}
}
As you can see, this requires a little type casting. Yo can avoid casting with generics, but this brings a complexity in types declaration:
interface IPaymentRequest<TTransaction>
where TTransaction : ITransaction
{
string Token { get; set; }
int ClientID { get; set; }
TTransaction Transaction { get; set; }
}
class Processor<TRequest, TTransaction>
where TRequest : IPaymentRequest<TTransaction>
where TTransaction : ITransaction
{
protected virtual void OnSetSettings(TRequest request)
{
}
private void SetSettings(TRequest request)
{
// do the common stuff
// ...
// set custom settings
OnSetSettings(request);
}
}
class PreAuthorizeRequestProcessor : Processor<PreAuthorizeRequest, PreAuthTransaction>
{
protected override void OnSetSettings(PreAuthorizeRequest request)
{
base.OnSetSettings(request);
// set custom settings here
}
}
Explanation to my comment (how to use visitor pattern in this case):
interface IPaymentRequest
{
void Process(IPaymentRequestProcessor processor);
}
class CaptureRequest : IPaymentRequest
{
public void Process(IPaymentRequestProcessor processor)
{
processor.Process(this);
}
}
class PreAuthorizeRequest : IPaymentRequest
{
public void Process(IPaymentRequestProcessor processor)
{
processor.Process(this);
}
}
interface IPaymentRequestProcessor
{
void Process(CaptureRequest request);
void Process(PreAuthorizeRequest request);
}
Where:
private void SetSettings(IPaymentRequest request)
{
IPaymentRequestProcessor processor = new PaymentRequestProcessor();
request.Process(processor);
}
The Visitor pattern is one obvious solution - it allows you to step around the fact that C# can't resolve which subtype of ITransaction you're using at runtime in order to choose a method overload by using a trick called double dispatch. The result of the Visitor pattern is to move the type-specific processing code from a conditional (which can miss cases) to a type definition, which the compiler can enforce the completeness of. The cost, however, is code that bounces around through virtual methods in a way that can be a bit complicated to figure out when you're trying to comprehend it from scratch.
Here's how it works.
ITransaction gains a method Accept(ITransactionVisitor visitor). ITransactionVisitor is an interface which has a Visit method with an override for each ITransaction subclass you want to deal with:
interface ITransactionVisitor {
void Visit(PreAuthTransaction t);
void Visit(VoidTransaction t);
// etc.
}
Then of course you need to implement these methods. Accept is easy, but it does need to be implemented for each implementation of ITransaction. Why? Not just because it's an interface method, but because within that method body the compiler will concretely know the type of the transaction at compile time, so it can choose the right overload in ITransactionVisitor.
public void Accept(ITransactionVisitor visitor) {
visitor.Visit(this);
}
Then all you need to do is implement an appropriate ITransactionVisitor. One of the advantages of this pattern is that you can implement as many as you like with completely different behaviours, and the ITransaction needs no further knowledge or modification (this is why the visitor is specified with an interface or an abstract class).
public class TransactionProcessorVisitor : ITransactionVisitor {
public TransactionProcessorVisitor(/* some suitable context in the constructor so it can do its job perhaps */) { ... }
public void Visit(PreAuthTransaction t) {
// do stuff
}
public void Visit(VoidTransaction t) {
// do other stuff
}
}
So yes, the visitor classes have to know about all the types of transaction, but
It's not in a giant if statement
It's not part of the ITransaction implementations
It's compile-time checked - if you add a new ITransaction type and try to feed it through the processor, the compiler will be able to figure out that there's no Visit method for it and throw an error, rather than waiting until runtime which is the best you can do with the if version.
This is not necessarily the best answer, but it's an answer.
First, let me tell you that your SetSettings method is wrong. var doesn't work like that. From there, your entire thread of reasoning is wrong. Add to it fact you are using some kind of "utility methods" and you have recipe for very bad architecture.
First, I would change those utility methods into some kind of full-featured classes with some interface. I'm sure you could create IProcessor interface and have PreAuthorizeProcessor and CaptureProcessor. From there, you either have IProcessor GetProcessor() method on your IPaymentRequest, which then forces each request into being able to have it's own processor. Or you could use a factory to create specific processor for given request via IProcessor CreateProcessor(IPaymentRequest). Here, you could either hard-code the preocessors or use some kind of subscribe mechanism.
Also, using type checking and casting is not wrong as long as it is properly encapsulated, like inside a factory. And using a visitor pattern is not much different from doing a manual type checking. You still get same kind of advantages and disadvantages from both.
I am writing a storage solution for a workflow hierarchy.
To simplify the picture I have 2 types of objects, a Workflow and a WorkflowStep.
Even though WorkflowStep comes hierarchically under the Workflow, the Workflow does not aggregate WorkflowStep because we view these objects as just data containers.
So this leaves me with the following classes:
public class Workflow : Node {
public string UID;
public string parentID;
}
public class WorkflowStep : Node {
public string UID;
public string parentID;
}
public class WorkflowEngine {
public void Store(Workflow wf) {
}
public void Store(WorkflowStep wfs) {
}
}
The reasoning for not aggregating WorkflowStep inside Workflow (even though logically that fits) is that these objects are purely viewed as data containers and they may be subject to changes later on and we want to keep the storage of these objects decoupled from the objects themselves.
The other alternative of course would be to do something like this:
public class Workflow : Node {
public List<WorkflowStep> steps;
public string UID;
public string parentUID;
public void Store() { }
}
public class WorkflowStep : Node {
public string UID;
public string parentID;
public void Store() { }
}
What are the pros and cons of either approach? Is there any literature that talks about both the designs?
Even though Workflow and WorkflowStep are both data containers but keeping these aside from hierarchical measures doesn't solve your decoupling issue.
It is more logical to keep WorkflowStep on hierarchy of Workflow and to get along with decoupling you must introduce IoC in this case.
The Beauty of IoC is that changing the definitions of WorkflowStep which is a list in Workflow class will be just transparent where you will only be considering to register your types on your IoC container.
Let me put you on an example with Ninject IoC container framework.
Define interfaces and implement your data containers accordingly:
public interface IWorkflow {
string UID { get; set; }
string parentID { get; set; }
IList<IWorkflowStep> Steps { get; set; }
}
public interface IWorkflowStep {
string UID { get; set; }
string parentID { get; set; }
}
public class Workflow : IWorkflow, Node {
public string UID { get; set; };
public string parentID { get; set; };
public IList<IWorkflowStep> Steps { get; set; }
}
public class WorkflowStep : IWorkflowStep, Node {
public string UID { get; set; };
public string parentID { get; set; };
}
And now, the Ninject module be:
public class WorkflowModule : NinjectModule
{
#region Overrides of NinjectModule
public override void Load()
{
Bind<IWorkflow>().To<Workflow>();
Bind<IWorkflowStep>().To<WorkflowStep>();
Bind<IList>().To<List>();
}
#endregion
}
This is the single place where you bind your interfaces with concrete classes. And rest of the world, you just ask for an instance of defined interface.
To resolve your type, you need to create a Ninject Kernel which is an IKernel type and a concrete implementation of StandardKernel by loading your defined module.
Which is something like,
var kernel = new StandardKernel(new WorkflowModule());
Now, all you have to do is resolve your desired interface, like:
IWorkflow workflow = kernel.Get<IWorkflow>();
IWorkflowStep workflowStep = kernel.Get<IWorkflowStep>();
The beauty here is, you don't need to worry about your concrete implementation and which is very tightly coupled within your system. Its just the interface you will be dealing with and rest are the worries of your IoC container implementation.
As you are more worried about the implementation of WorkflowStep to be changed and not coupling with Workflow. I guess, this is where IoC comes to play.
Please be noted that, you can use any IoC container framework like Unity, Spring.NET, StructureMap and etc. I used Ninject because I am comfortable with it.
Im faced with an impending upgrade to an ASP.NET site and I am thinking of introducing DI using Unity. I have researched the ASP.NET DI side of things and have 2 options (Global.asax or IHttpModule). Im happy to use either.
As always, there is a legacy object model in place that I would like to upgrade/change. I would like to go down the route of Constructor injection (passing in the DAO) however, each object has a mix of static and instance methods that both currently call into the DB using SqlCommand objects themselves. I want this removed to provide DB independence, therefore can anyone suggest the best way to do the DI in this case? Im open to drastic changes if they are needed.
public class ExampleClass
{
public ExampleClass(int test)
{
TestProperty = test;
}
public int TestProperty {get; set;}
public int Save()
{
// Call DB and Save
return 1;
}
public static ExampleClass Load(int id)
{
// Call DB and Get object from DB
return new ExampleClass(1);
}
}
Thanks for any suggestions
Matt
If you remove all static methods and introduce some abstractions you should be good to go:
public class ExampleClass
{
public int TestProperty { get; set; }
}
public interface IRepository
{
ExampleClass Load(int id);
int Save();
}
public class RepositorySql: IRepository
{
// implement the two methods using sql
}
and in your ASP page:
private IRepository _repo = FetchRepoFromContainer();
public void Page_Load()
{
var someObj = _repo.Load(1);
// ... etc
}