I was asked to use a table to store status of an entity type. Normally I used always enums for that before.
There is a business logic in which the status of the entity changing. This logic is encapsulated in the entity. It was easy when the status was an enum type. But now I would need to inject a service to get the required status. I do not know if it is a good idea to inject a service (like StatusService) into that method making the method depend on IStatusService.
Example code:
public class MyEntity
{
public MyEntityStatus Status { set; get; }
public void MethodInWhichStatusMayChange(IMyEntityStatusService myEntityStatusService)
{
//using myEntityStatusService to get the status when it should change
}
}
public class MyEntityStatus
{
public string Name { set; get; }
}
public interface IMyEntityStatusService
{
MyEntityStatus GetStatusA();
MyEntityStatus GetStatusB();
MyEntityStatus GetStatusC();
}
It is better to inject the service in the class constructor:
public class MyEntity
{
private readonly IMyEntityStatusService myEntityStatusService;
public MyEntity(IMyEntityStatusService myEntityStatusService)
{
this.myEntityStatusService = myEntityStatusService;
}
public MyEntityStatus Status { set; get; }
public void MethodInWhichStatusMayChange()
{
//now you use the private myEntityStatusService field
}
}
This will make your life easier if you decide to use a dependency injection engine, and also your code will be cleaner, easier to use (you don't have to be passing around instances of IMyEntityStatusService), and as pointed out in the comments, easier to test.
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'm trying to perform a mapping between an EF domain object to a DTO object using the Automapper 'Project' method, but am having problems when trying to project from an interface to a concrete class. My EF domain object implements an interface that I use commonly with my lookup tables:
public interface ILookupItem
{
int Id { get; set; }
string Name { get; set; }
}
and here's an example of my domain object:
public partial class ReportType : ILookupItem
{
public int Id { get; set; }
public string Name { get; set; }
}
In my app, I'm using a DTO object which exactly matches the domain object interface:
public class LookupItemModel
{
public static void CreateMapping(IConfiguration configuration)
{
configuration.CreateMap<ILookupItem, LookupItemModel>();
}
public int Id { get; set; }
public string Name { get; set; }
}
I then perform my database query with a call such as:
return DbContext.Query<ReportType>().Project().To<LookupItemModel>();
however on this call Automapper gives an error about missing a required mapping to perform the function:
Missing map from ReportType to LookupItemModel. Create using Mapper.CreateMap<ReportType, LookupItemModel>.
I would have assumed that the mapping could be performed from the interface since all it should need to know are the properties which to pull data for (Id & Name). Am I missing something to be able to perform this projection without creating maps for each concrete implementation of my interface?
Thanks!
I asked in a comment but haven't had a response yet but I'm fairly sure this is your problem so I'm going to go ahead and make it an answer.
You're creating the mapping between ILookupItem and LookupItemModel but you aren't ever calling the method that creates the map - LookupItemModel.CreateMapping().
Before you do the mapping you need to call this method:
LookupItemModel.CreateMapping(your IConfiguration);
return DbContext.Query<ReportType>().Project().To<LookupItemModel>();
That said, instead of setting up your mapping logic inside your models, I would create an AutoMapper configuration class that sets up all your maps. Something like:
public class AutoMapperConfig {
public static CreateMaps() {
CreateLookupItemMaps();
}
public static CreateLookupItemMaps() {
Mapper.CreateMap<ILookupItem, LookupItemModel>();
}
}
Or a cleaner approach would be to use AutoMapper Profiles
And then call AutomapperConfig.CreateMaps() during your app startup and you should be good.
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.
This is a continuation of an issue I'm still experiencing here. I'm trying to prevent the OData reflection provider from trying to expose ALL of the CLR classes in my assembly.
Consider the following CLR class:
public class Foo
{
public Guid FooID { get; set; }
public string FooName { get; set; }
}
And the following class to expose Foo as an IQueryable collection:
public class MyEntities
{
public IQueryable<Foo> Foos
{
get
{
return DataManager.GetFoos().AsQueryable<Foo>();
}
}
}
And the following DataService class:
public class MyDataService : DataService<MyEntities>
{
public static void InitializeService(DataServiceConfiguration config)
{
config.SetEntitySetAccessRule("Foos", EntitySetRights.All);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
}
}
This all works hunkey dorey and the DataService can display a collection of Foo. But if change Foo to extend a very simple base object such as:
public class Foo : MyObjectBase
{
public Guid FooID { get; set; }
public string FooName { get; set; }
}
Then (even though I'm only trying to expose 1 collection), the reflection provider grabs ALL objects that extend MyObjectBase, causing loads of errors.
The base class is a simple abstract class that implements a number of interfaces and provides another property such as:
public abstract class MyObjectBase: IDataObject, IDataErrorInfo, INotifyPropertyChanged, IDisposable
{
public virtual Guid ID { get; set; }
}
Even putting IgnoreProperties on any public properties here doesn't help. Is there any way to dial down what the reflection provider is doing?
You could set:
config.SetEntitySetAccessRule("TypeNotAccessible", EntitySetRights.All);
to
config.SetEntitySetAccessRule("TypeNotAccessible", EntitySetRights.None);
On any classes you don't want accessible. I do this using the help of a custom attribute that indicates the rights I want for a particular class. This in combination with looping over all known types (that implement my attribute), makes it possible to do this without explicit code to set each class individually.
I was unable to find a way to dial down the reflection provider with a rich data model. I ended up building a custom provider as indicated here.
If someone provides a way to dial down the reflection provider, I'll accept that answer.
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.