I have the need to extend instances of various types at runtime. Most of the time, I need to work with instances of the original type, however in a few circumstances, I need to create kind of an extension-wrapper around those types that add a couple pieces of contextual information. Something along the lines of the following (which is not actually valid .NET/C# code...but it illustrates the point):
public abstract class BaseClass
{
// ...
}
public class Concrete1: BaseClass
{
// ...
}
public class Concrete2: BaseClass
{
// ...
}
public class WrapperExtender<T>: T // Extending from T here is actually invalid!
where T: BaseClass
{
public WrapperExtender(T extensionTarget)
{
m_extensionTarget = extensionTarget;
}
private readonly T m_extensionTarget;
public object ContextualReference { get; }
public int ContextualValue { get; }
// DERP: Would need to implement overrides of T here...buuut...can't...
}
// In use, special case:
var instance = new Concrete1();
var extendedInstance = new WrapperExtender(instance);
var processor = new SomeProcessorRequiringExtendedInstance();
processor.DoProcessing(extendedInstance);
Another example of this would probably be Microsoft Entity Framework v4.0, or nHibernate. Both of these frameworks provide dynamically extended instances of your entity types, wrapping them internally to provide, at runtime, the hooks required to keep a data/object/session context up to date with changes made to your entity instances. My needs are not nearly as complex, and the generics scenario above would work beautifully, if only there was a way to blend generics and dynamic typing somehow.
Anyway, I'm hoping someone knows how to achieve the above scenario. Or, perhaps even better, someone knows a better solution. I don't care much for the idea of dynamically extending a type like that at runtime (it doesn't make as much sense as it does in the EF/nHibernate scenario.) At the moment, its the only thing I can really think of that will provide me with the information I need in the processor for each type passed in to DoProcessing.
The problems that EF etc are solving is different, and relates to tihngs like lazy loading, etc. I'm simply not sure that the level of complexity that dynamic subclassing requires is worth it for this scenario. A few thoughts, though:
have a property bag in your object for flexible additional properties; if necessary the property-bag can be exposed to data-binding APIs via ICustomTypeDescriptor
simply wrap your object in an implementation-specific tuple that contains the existing object and the additional properties (no subclassing)
It is a shame that C# doesn't support "mixins", which would also be a nice way of implementing this type of thing with interfaces.
I know that this can be accomplished using dynamicproxy (which is what NHibernate uses to accomplish this task) which you can find out more about here:
DynamicProxy Page
DynamicProxy tutorial
If all you need is some additional properties, why not just create a context property in BaseClass?
something like this, where ContextBag is either a generic collection class or specially defined context collection:
Public ContextBag Context
{
get;
set;
}
When setting/accessing the context, you will be using syntax like this:
SubClass.Context.GetInt(ContextDefinition, ContextName);
SubClass.Context.Add(ContextDefinition, ContextName, ContextValue);
Found a better solution than temporarily extending. I created an actual context object that contained the state I needed available. Whenever that context exists, I initialize the context and set a static property that can be used to retrieve the context object from anywhere, alleviating the need to update all the dependencies of my larger process to take the context in as a parameter (which isn't always possible, as sometimes the calls are made in other contexts.)
public class SomeContext
{
public SomeContext(object stateData1, object stateData2)
{
StateData1 = stateData1;
StateData2 = stateData2;
}
public virtual object StateData1 { get; private set; }
public virtual object StateData2 { get; private set; }
[ThreadStatic]
private static SomeContext m_threadInstance;
public static SomeContext Current
{
get
{
return m_threadInstance;
}
set
{
if (value != null && m_threadInstance != null)
throw new InvalidOperationException("This context has already been initialized for the current thread.");
m_threadInstance = value;
}
}
}
public class SomeContextScope: IDisposable
{
public SomeContextScope(object stateData1, object stateData2)
{
if (SomeContext.Current == null)
{
SomeContext context = new SomeContext(stateData1, stateData2);
SomeContext.Current = context;
m_contextCreated = true;
}
}
private bool m_contextCreated;
public void Dispose()
{
if (m_contextCreated)
{
SomeContext.Current = null;
}
}
}
public class ComplexProcessor
{
public ComplexProcessor(...) // Lots of dependencies injected
public void DoProcessing(BaseClass instance)
{
// do some work with instance
if (SomeContext.Current != null)
{
// do contextually sensitive stuff for SomeContext with instance
// call a dependency that does contextually sensitive stuff
}
// do some more work with instance
// call a dependency that does contextually sensitive stuff
if (SomeOtherContext.Current != null)
{
// do contextually sensitive stuff for SomeOtherContext with instance
// call a dependency that does contextually sensitive stuff
}
// call a dependency that does contextually sensitive stuff
}
}
// The original setup of the context and initiation of processing
public void SomeOperation(...)
{
using (SomeContextScope scope = new SomeContextScope(stateData1, stateData2))
{
// ... do some work
var processor = complexProcessorFactory.CreateInstance();
processor.DoProcesing(data);
// ... do more work
}
}
I like the way this works. Context is the state within which behavior executes. It has always felt clunky to me to have to pass contextual data around with other objects, and have dozens of methods or method overloads that take in and pass along various forms of contextual data. By setting up a context object that is globally available for the duration of that context, my code is a lot cleaner, and my dependencies are more concise. It should be mockable too, since the Current property is read/write, I can create a mock context in a BDD specification or TDD unit test whenever one is required without a lot of hassle.
Related
What is a good (object oriented) way of setting a property of a class which implements an interface, when that property doesn't always exist in all classes that implement that same interface?
e.g.
Let's say I have an interface
public interface IDataRepository {
public DataStructure GetData(); // DataStructure is an arbitrary class, doesn't matter for this example
}
Now I also have two classes that inherit from this
public class DatabaseRepository : IDataRepository {
public DataStructure GetData()
{
// get data from database
}
}
and
public class FileRepository : IDataRepository {
public string WorkingFolder { get; set; }
public DataStructure GetData() {
// get data from files
}
}
Now my client method doesn't necessarily know what the repository is but here's what I want to do...
private DataStructure ReadData(IDataRepository repository)
{
repository.WorkingFolder = #"C:\Data"; // What is the best way of doing this?
return repository.GetData();
}
obviously the above code won't work and I could do...
if (repository is FileRepository) {
((FileRepository)repository).WorkingFolder = #"C:\Data";
}
or add WorkingFolder as a property of the interface (and therefore all the classes that implement it) even though in most cases it's irrelevant.
but both of these (esp. the first one) seem very inelegant and not very object oriented. What is the oop way of doing this kind of thing?
Edit
The obvious question is if the method doesn't know what repository is, how can it know the correct value for WorkingFolder... But the above is an over-simplification of what I'm trying to do, so let's just say it can find out...
Apparently your ReadData method can't actually accept any type of repository. It is only able to handle a FileRepository. That's what it expects, and that's what it needs to do its job. Given that, that's what it should actually accept as its parameter, rather than an interface that doesn't actually provide a contract that is sufficient for it to do its job.
The entire point of having an interface is so that anyone using that interface can use it without caring what the implementation is. So if you do want to use the interface you need to include enough information in the interface's definition such that it provides every operation that anyone using the interface needs, otherwise you're better off just not using it at all (at least for that specific operation).
As for the specific example given, you should probably just be providing an already configured repository, that has whatever values it needs in order to allow this method to do its work, as a parameter. It doesn't make sense for a method that's reading a value from an arbitrary repository to be configuring that repository at all. That is, if it really is reading something from an arbitrary repository.
As others have said in the comments, you should initialise these properties in the constructor. This is where you know what type you're creating, so you also know what arguments its constructor requires / can set those there.
Once you've initialised the object, you can just pass it around / have anything using that class operate against its interface.
Example:
public void Main(string[] args)
{
var myRepo = new FileRepository(args[0]); //Here's where we set the working directory
var myThing = new Thing();
var data = myThing.ReadData(myRepo);// of course, the current implementation means you could just call `myRepo.GetData()` directly, since ReadData just passes out the same response; but presumably that method adds some additional value..
Console.WriteLine(data.ToString());
}
Supporting Code
public class DatabaseRepository : IDataRepository {
DbConnection connection; //you may want a connection string or something else; going with this type just to illustrate that this constructor uses a different type to the FileRepo's
public DatabaseRepository(DbConnection connection)
{
this.connection = connection;
}
public DataStructure GetData()
{
// get data from database
}
}
public class FileRepository : IDataRepository {
public string WorkingFolder { get; set; } //Do you need set? Generally best to keep it constant after initialisation unless there's good reason to change it
public FileRepository (string workingFolder)
{
this.WorkingFolder = workingFolder;
}
public DataStructure GetData() {
// get data from files
}
}
How do I call the code that creates the class
i.e. maybe you've implemented a really basic factory pattern like so, and want to know how to provide arguments:
public class DataRepositoryFactory
{
Type baseType = typeof(IDataRepository);
IDictionary<string, Type> typeMap = new Dictionary<string, Type>() {
{"File", typeof(FileRepository) }
,{"Db", typeof(DatabaseRepository) }
}
public void RegisterType(string typeName, Type type)
{
if (!baseType.IsAssignableFrom(type)) throw new ArgumentException(nameof(type));
typeMap.Add(typeName, type);
}
public IDataRepository GetDataRepository(string typeName)
{
return (IDataRepository)Activator.CreateInstance(typeMap[typeName]);
}
}
(For a more complex example of a factory, see https://web.archive.org/web/20140414013728/http://tranxcoder.wordpress.com/2008/07/11/a-generic-factory-in-c).
I.e. in this scenario, when you call the factory you know what type you want, but you're only giving it a string to name/identify that class. You could add a params object[] args to your GetDataRepository method, allowing you to call it like so:
var myRepo = myDataRepositoryFactory.GetDataRepository("File", "c:\somewhere\something.dat");
That's a good approach / is actually what's used on the linked example above. However, it means that your call to this code differs for different types; since if we use variables instead of hardcoded values as in the above example we can't simply do the below, since myRepoType could be set to "Db", whilst "myFilePath" would be a string:
var myRepo = myDataRepositoryFactory.GetDataRepository(myRepoType, myFilePath);
That's fixable by calling:
var myRepo = myDataRepositoryFactory.GetDataRepository(myRepoType, myArgs);
i.e. where myArgs is an object[], giving all of the values required in the desired order to initialise the type. The piece to populate object[] with the required values could then take place at the same point at which you decided you wanted the type to be a file repo vs database repo. However, this approach isn't that clean / casting to and from objects stops you from getting help from the compiler.
So how do I improve things?
There are a few options. One is to replace the need to use object[] by instead creating a type to hold your arguments. e.g.
public interface IDataRepositoryConfiguration
{
//nothing required; this is just so we've got a common base class
}
public class FileRepositoryConfiguration: IDataRepositoryConfiguration
{
public string WorkingFolder {get;set;}
}
public class FileRepository : IDataRepository {
public FileRepository (IDataRepositoryConfiguration configuration)
{
var config = configuration as FileRepositoryConfiguration;
if (config == null) throw new ArgumentException(nameof(configuration)); //improve by having different errors for null config vs config of unsupported type
this.WorkingFolder = config.WorkingFolder;
}
//...
}
This still has some issues; i.e. we may pass a DatabaseRepositoryConfiguration as our IRepositoryConfiguration when creating a FileRepository, in which case we'd get the AgumentNullException at runtime; but this does avoid issues should parameters change order, and makes it less of a headache to code / debug.
Could it be further improved?
Dependency Injection offers one solution. This could be used along the lines of the code below (i.e. you create instances of each of your classes, providing the required arguments, and give each instance a name, so that you can later fetch that instantiation. Exactly what that code looks like would depend on the dependency injection library you used:
//setting up your repositories
var container = new Container();
container.Configure(config =>
{
// Register stuff in container, using the StructureMap APIs...
config.For<IDataRepository>().Add(new FileRepository("\\server\share\customers")).Named("customers");
config.For<IDataRepository>().Add(new FileRepository("\\server\share\invoices")).Named("invoices");
config.For<IDataRepository>().Add(new DatabaseRepository(new DbConnection(configurationString))).Named("persist");
config.For<IDataRepository>().Use("persist"); // Optionally set a default
config.Populate(services);
});
//then later when you need to use it...
public DataStructure ImportCustomers(IContainer container)
{
var customerRepo = container.GetInstance<IDataRepository>("customers");
return customerRepo.GetData();
}
I'm sure there are many other approaches, and exactly what approach to use depends on how your program will operate. Hopefully the above is enough to get you past your current problem; but if you find you're still struggling please post a new question with more detail / saying where you're still having issues having considered these points.
If possible, I'd just put the value for that property in the constructor or create a subinterface, like others suggested.
If it's not possible, C# 7.X (don't remember the exact minor version) has a nice code structure for conditional casting:
IDataRepository repo = new FileRepository();
if (repo is FileRepository fileRepo)
{
fileRepo.WorkingFolder = "some dir";
}
However in your case, you should probably rethink your architecture and always pass (or even better always create) a repository object which is ready to be used.
a) Put it into the Inferface definitions. Deal with any "NotImplemented" Exceptions. You always have to expect those with Interfaces anyway.
For example, IEnumerable has a Reset() function. But in most cases it is not implemented. It is not even supposed to be implemented in most cases. Afaik it is only there for Backwards Compatabilty with some old COM stuff.
b) make a sub-interface just for the property
c) Verify the Interface is properly implemented via is checks (throw exceptions thows if nessesary, like Array.Sort will throw a InvalidOperation one), generic constraints, proper argument types and the like.
So we have ran into what seems like a very common issue with StructureMap and IoC containers in general I assume. Bidirectiona/Circuar dependencies.
Given the following code, it is currently causing a circular dependency since we have it 'autowiring' properties.
public class ServiceA:IServiceA
{
public IServiceB ServiceBDependency {get;set;}
}
public class ServiceB:IServiceB
{
public IServiceA ServiceADependency {get;set;}
}
I see the 'dependency' of each of these on eachother, however, I feel that as a property, they are not true dependencies which is what separates them from using constructor injection.
It seems that there should be a way for these services to be resolved...and then have the properties injected after the objects have been created?
I know of various ways to get around this, including the true clean way of rearchitecting my services, but i am curious as to what options I have with instantiation and service registration with StructureMap. It seems like a fairly common issue that would need a solution.
I'd like to show you my approach. I am using only the setter injection. And we often have many objcets referencing each other, in our web app. E.g. IUserFacade requires IUserState on user creation while IUserState requires IUserFacade on userState deletion (to check for constraint).
e.g.:
public interface IUserFacade
{
... // User facade Add, Update, Delete
IUserStateFacade { set; }
}
public interface IUserStateFacade
{
...
IUserFacade { set; }
}
In reality, we have many objects with cross references, and even more complicated. And it would really be very costy, if all the referenced objects should be created each time, even if not used during the request. We need the "lazy", the proxy objects to be placed in the setters.
The way how to do it, is a mix of the: 1) StructureMap (IoC top) and 2) Castle (proxying top) libraries. Below I will show some snippets of objects needed for this solution. More could be found inside open source project Catharsis
Wrapper. This object would be injected into each Property by SM (StructureMap) instead of real implementor. It is the sleeping implementation. It is waiting for a first call. If it will never happen (IUserFacade is deleting user, no need to access referenced IUserStateFacade during such request) this wrapper will sleep for ever (request). Once touched, SM will create the real object and Wrapper will pass all calls to that.
The Castle interceptor:
public class Wrapper : IInterceptor
{
object _lazy;
protected readonly Type Type;
public Wrapper(Type type)
{
Type = type;
}
public void Intercept(IInvocation invocation)
{
if (_lazy.IsNull()) // lazily instantiate the instance
{
_lazy = ObjectFactory.GetInstance(Type);
}
try
{
var method = invocation.Method;
if (method.ContainsGenericParameters)
{
method = method.MakeGenericMethod(invocation.GenericArguments);
}
invocation.ReturnValue = method.Invoke(_lazy, invocation.Arguments);
}
catch (TargetInvocationException ex)
{
// PublishingManager.Publish(.... // publish exception
throw;
}
}
}
ProxyInstance. Now, we need an object, clear and understandable to SM. That object will be mapped to all interfaces (IUserFacade...) Instead of returning implementation of the UserFacade.
We can also use our custom AOP filters here.
This ProxyInstance will be provided with the real implementor type, and building up the Wrapper.
The StructureMap Instance:
public class ProxyInstance : Instance
{
protected readonly ProxyGenerator Factory = new ProxyGenerator();
protected readonly Type ConcreteType;
public ProxyInstance(Type type)
{
ConcreteType = type; // the type for our Wrapper, the real implementation
}
protected override object build(Type pluginType, BuildSession session)
{
var aopFilters =
// my custom way how to inject more AOP filters
AopFilterManager.GetFilters()
// the core for us, one of the interceptors is our Wrapper
.Union(new[] { new Wrapper(ConcreteType) })
.ToArray();
// Castle will emit a proxy for us, but the Wrapper will do the job
var proxy = Factory
.CreateClassProxy(ConcreteType, AopFilterManager.AopOptions, aopFilters);
return proxy;
}
And now just use some standard way how to map it in the SM (I am using custom ProxyConvention but it is out of the scope here). Let's use simplified explicit mapping:
registry
.For<IUserFacade>()
.HybridHttpOrThreadLocalScoped()
.Use(new ProxyInstance(typeof(UserFacade)));
...
Also, each of our objects created via SM, implements IService. So, the default setter injection could be set like this:
registry.SetAllProperties
(
set => set.TypeMatches
(
type => type
.GetInterfaces()
.Any(i => i.IsEquivalentTo(typeof(IService)))
)
);
From that moment, when we need to work with a IUserFacade (the direct ObjectFactory call, or accessed via Wrapper), we recieve the real implementor. All its properties (setter injection) will be pre-populated with our ProxyInstance / Wrapper.
If any of these properties is accessed, e.g. IUserStateFacade the same (discribed above for IUserFacade) will happen again.
Because the Lifecycle is Thread or Request based, we have only one implementor in runtime/web request
Because we do inject the Wrappers while using setter injection, no issues with circular infinite loops. Only the first level is injected each time
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Constructor vs. Factory in .NET Framework
I understand factory patten and have implemented it but couldn't get what benefit it will bring. For example instead of:
MyType1 obj=new Mytype1();
MyType2 obj=new Mytype2();
writing:
IMyType obj1 = Factory.Create(1);
IMyType obj2 = Factory.Create(2);
Is it something I have missed or not conceive. Can you please put your own experience example.
Some benefits of the factory pattern:
You can keep track of the objects you create. If you want to re-use objects or enforce a limit on the number of objects created, the factory can enforce that.
You can control how objects are created. If there are some parameters used to create the objects, you can return an existing object when clients pass in the same parameters for an object that has already been created.
You can have the factory return an interface but internally create different types of objects that support the interface.
Factory patterns are good for many reasons
A couple of them are:
you can initialise the item in the factory (default values etc) and make the item creation procedural (look at other classes/procedures, get defaults, inspect configuration values).
A constructor is one way to create an item but you can't inspect other classes or run other processes that are outside of the newly created instance without tightly coupling the class to these dependencies
it provides a central repository for item creation which enforces patterns/practices amongst developers in your team
Those are some of the reasons I can think of :)
e.g.
This class is dependent on the ConfigManager for instantiation
class SomeClass
{
public int SomeValue;
public SomeClass()
{
// Check the config for some value
SomeValue = ConfigManager.GetDefaultInt("SomeValue");
}
}
This class is not because it uses a factory
class SomeClass
{
public int SomeValue;
public SomeClass()
{
}
}
class SomeClassFactory
{
public SomeClass CreateSomeClass()
{
SomeClass obj = new SomeClass();
obj.SomeValue = ConfigManager.GetDefaultInt("SomeValue");
}
}
The benefit of the Factory pattern is that it encapsulates the details of construction and specific type from how it is used. This allows you to evolve to more interesting designs later with fewer places to make a change.
Consider this example:
public interface IStorage
{
void Save(SomeObject toSave);
SomeObject Get(SomeId id);
}
public class DatabaseStorage : IStorage
{
public void Save(SomeObject toSave)
{
//persist to DB somehow
}
public SomeObject Get(SomeId id)
{
//get from db somehow and return
}
}
public class StorageFactory
{
public IStorage GetStorage()
{
return new DatabaseStorage();
}
}
public class DatabaseStorage : IStorage
{
public void Save(SomeObject toSave)
{
//persist to DB somehow
}
public SomeObject Get(SomeId id)
{
//get from db somehow and return
}
}
Now imagine you later get the requirement to cache some results, or to log all results. You could create a proxy, like this:
public class LoggingStorage : IStorage
{
private readonly IStorage _proxied;
public LoggingStorage(IStorage proxied)
{
_proxied = proxied;
}
public void Save(SomeObject toSave)
{
//log this call
_proxied.Save(toSave);
}
public SomeObject Get(SomeId id)
{
//log this call
return _proxied.Get(id);
}
}
Now, if you used a constructor, you have to replace every use of it to wrap it with this. If you used the factory, you only change it:
public class StorageFactory
{
public IStorage GetStorage()
{
return new LoggingStorage(new DatabaseStorage());
}
}
Of course, speculative factories can seem a little heavy handed for this, which is why I prefer to encapsulate the constructor.
jQuery is a factory function that takes advantage of the way JavaScript works to create objects with a very low memory footprint.
Let's investigate with a horribly mutilated, drastically simplified version of jQuery to help see the potential benefits:
var $ = jQuery = (function(){ //this anon function fires once, and returns a function
//defines all kinds of internal functions jquery uses here
function jQuery(selector,context){ // we're going to return this inner JQ later
//defines only the logic needed to decide what to do with the arguments here
//and then builds the jQuery object with 'return new jQuery.prototype.init();'
}
//defines jQuery.prototype properties here:
jQuery.prototype = {
//...
init:function(selector,context){ //gets used to build the JQ objects
this.constructor.prototype = jQuery.prototype; //hands off the function prototype
}
//...
}
return jQuery; //this gets assigned to the outer jQuery and $ vars
})()
So... now we have a factory function that is also something like a namespace whose prototype we can extend, and expect those methods to be available on the object it spits out. Furthermore, the objects themselves have very little weight in memory aside from the DOM objects they typically wrap because all functions are references pulled in from closure or the outer prototype object that gets handed off as a reference. Aside from a bit of logic and some state vars, everything the object needs is built when jQuery first gets parsed or handed down from the prototype object as you add new methods to factory function's prototype property.
Now, try to do that with new jQuery()
If anything, applying the factory pattern in JavaScript can be immensely and uniquely powerful.
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.
All of our reports are created from object graphs that are translated from our domain objects. To enable this, we have a Translator class for each report, and have been using Dependency Injection for passing in dependencies.
This worked great, and would yield nice classes structured like this:
public class CheckTranslator : ICheckTranslator
{
public CheckTranslator (IEmployeeService empSvc
, IPaycheckService paySvc)
{
_empSvc = empSvc;
_paySvc = paySvc;
}
public Check CreateCheck()
{
//do the translation...
}
}
However, in some cases the mapping has many different grouping options. As a result, the c-tor would turn into a mix of class dependencies and parameters.
public class CheckTranslator : ICheckTranslator
{
public CheckTranslator (IEmployeeService empSvc
, IPaycheckService paySvc
, bool doTranslateStubData
, bool doAttachLogo)
{
_empSvc = empSvc;
_paySvc = paySvc;
_doTranslateStubData = doTranslateStubData;
_doAttachLogo = doAttachLogo;
}
public Check CreateCheck()
{
//do the translation...
}
}
Now, we can still test it, but it no longer really works with an IoC container, at least in a clean fashion. Plus, we can no longer call the CreateCheck twice if the settings are different for each check.
While I recognize it's a problem, I don't necessarily see the right solution. It seems kind of strange to create a Factory for each class ... or is this the best way?
Shot in the dark here, but could you move those parameters to the method instead?
In other words:
public Check CreateCheck(bool doTranslateStubData, bool doAttachLogo)
{
//do the translation...
}
Do those parameters have to be passed in via the constructor?
(Note - if your response to this is "there are too many methods for that to be practical", then part of the problem may be that the abstraction is too coarse).
Another option (it's really hard to say without understanding the domain model and injection patterns) would be to introduce a parameter object that is itself managed by the injector:
public interface ICheckConfiguration
{
bool AttachLogo { get; }
bool TranslateStubData { get; }
}
Then inject this with the constructor:
public CheckTranslator (IEmployeeService empSvc, IPaycheckService paySvc,
ICheckConfiguration config)
{
// etc.
}
This should be enough. You can then create a concrete CheckConfiguration class that takes those two bool properties in its constructor, and configure your container to create different instances of the parameter object (interface) based on a higher-level DI parameter.
The last thing I think I should mention is that just because you're using DI doesn't mean that everything has to be managed by the container. It's not such a bad thing to create CheckTranslator objects in an ad-hoc fashion if there's only one kind of "translator". As long as the translator still depends on abstractions, which it does here, then maybe you shouldn't be injecting it at all, just let higher-level DI-enabled classes create them ad-hoc.