Iโm not even sure what to look for on this problem, so I decided that I would post it here.
Let's say I have a set of interfaces like ...
/// <summary> /// All interesting classes will implement this interface /// </summary> interface IMasterInterface {} /// <summary> /// Interface to represent someone that creates / produces goods /// </summary> interface IProduceGoods : IMasterInterface { int Prop1 {get;} } /// <summary> /// Interface to represent someone that buys / consumes goods /// </summary> interface IConsumeGoods : IMasterInterface { int Prop2 {get;} } /// <summary> /// Interface to represent someone that stores goods /// </summary> interface IStoreGoods : IMasterInterface { double Prop3 {get;} string name {get;}} /// <summary> /// Interface to represent someone that enjoys looking at goods /// </summary> interface IEnjoyLookingAtGoods : IMasterInterface { int Prop4 {get;} DateTime Prop5 {get;} }
Now I have some combination that I know, I want today, something like:
/// <summary> /// Class to represent a farm which grows and stores crops /// </summary> class Farm : IProduceGoods, IStoreGoods {/*...*/} /// <summary> /// Class to represent a merchant who buys goods and stores them /// </summary> class Merchant : IConsumeGoods, IStoreGoods {/*...*/} /// <summary> /// Window Shopper represents someone who doesn't buy anything and only looks /// </summary> class WindowShopper : IEnjoyLookingAtGoods{ /*...*/ }
Now I'm glad that I have several classes, but tomorrow, I think it would be nice to also have a class in which someone really buys from the seller, so I would go to my code and add
/// <summary> /// Princesses have lots of money to buy stuff and lots of time to look at stuff /// </summary> class Princess : IEnjoyLookingAtGoods, IConsumeGoods {/*...*/}
Now I donโt think I need to do this ...
What I would like to do is to have a factory (or similar) thing and say:
IMasterInterface princess = MyFactory.Create(IEnjoyLookingAtGoods, IEnjoyLookingAtGoodsParameters, IConsumeGoods, IConsumeGoodsParameters)
Essentially, I would like to tell a factory that uses interfaces to create an object. I have containers with IMasterInterface lists
Now, this is where the meat of the question lies. The reason that all of the interesting classes implement IMasterInterface was to have a list and use more specific interfaces as filters. Perhaps the following will be more clear:
Filtering out for a more specific interface, now I can count on all objects passed to DoSomethingWithListToAggregate (manufacturers of ICollection) with methods / properties of the IProduceGoods class.
I thought about implementing this with dictionaries and distortion of string properties, but it seems to me that I can write more strongly typed code in this way and make sure that a simple spelling error somewhere is not going to ruin everything.
Anyway, I think the summary:
Is this a bad way to implement variable properties for an object, and if so, what would be better. If not, is there a way to create objects in the factory, as I tried to explain above?
EDIT:
I see some ideas for this, and that's cool. I was wondering how to create a factory that accepts the arguments of an interface that has only properties and properties have only getters (I think the important point) together with the property values โโfor the properties and returns an object that implements the interface and has all the specific properties.
For instance,
I would pass the factory all the interfaces and their parameter values, and he would create some class that implements these interfaces and has these values. Hope this is a little more clear?
EDIT 2: How to use Decorator?
From what I see about the decorator, you can extend the functionality of the object. It's great. However, you must know in advance how to extend this functionality. You cannot do this arbitrarily.
Note that my code base is the same as above, and I want to use a decorator.
I would say:
// Edited to be correct class EnjoyLookingDecorator : IEnjoyLookingAtGoods { private IMasterInterface instance; public EnjoyLookingDecorator(IMasterInterface wrappedObject) { this.instance = wrapped Object;}
EDIT 4:
I still don't think this will work. In your example, I am losing the class interface, I have to redirect it. For instance,
class EnjoyLookingDecorator : IEnjoyLookingAtGoods { private IMasterInterface instance; public EnjoyLookingDecorator(IMasterInterface concrete) { this.instance = concrete;} #region Implementation of IEnjoyLookingAtGoods here /*...*/ #endregion bool Is<T>() //this should be in the IMasterInterface { return this is T or instance is T; } } class ConsumesGoodsDecorator : IConsumeGoods { private IMasterInterface instance; public ConsumesGoodsDecorator (IMasterInterface concrete) { this.instance = concrete;} #region Implementation of IConsumeGoods here /*...*/ #endregion bool Is<T>() { return this is T or instance is T; } }
so when you d
IMasterInterface princess = new MasterClass() //whatever your concrete type is named princess = new ConsumesGoodsDecorator(new EnjoyLookingDecorator(princess))
you can no longer do princess.PropertyOnIEnjoyLookingDecoratorInterface you lose all these properties. This is not what I want. The only way to save properties is to redirect
class ConsumesGoodsDecorator : IConsumeGoods, IEnjoyLookingAtGoods { private IMasterInterface instance; public ConsumesGoodsDecorator (IMasterInterface concrete) { this.instance = concrete;} #region Implementation of IConsumeGoods here /*...*/ #endregion #region Redirect all the IEnjoyLookingAtGoods Property Getters to instance /* ... */ #endregion bool Is<T>() { return this is T or instance is T; } }
When performing the redirection, we must implement the interface. Then all combinations have code, which I am trying to avoid. I have no restrictions on combinations of interfaces.
EDIT 5:
Perhaps I am still unclear in my question. Imagine the interfaces as they are above, with their properties populated.
If the factory can do something like this:
I understand that this is not how it will actually work, but it illustrates what I'm trying to do. I want the object to implement a dynamic combination of interfaces and have default values โโfor setters.
Even if I could do something like factory, write a text file containing the code:
/// <summary> /// Auto Generated by Factory to create a new type on the fly /// </summary> class ClassImplementingIProduceGoodsAndIEnjoyLookingAtGoods : IProduceGoods, IEnjoyLookingAtGoods { // From IProduceGoods public int Prop1 {get; private set;} // From IEnjoyLookingAtGoods public int Prop4 {get; private set;} public DateTime Prop5 {get; private set;} public ClassImplementingIProduceGoodsAndIEnjoyLookingAtGoods(int prop1, int Prop4 , DateTime Prop5) { this.Prop1 = prop1; this.Prop4 = Prop4; this.Prop5 = Prop5; } }
Then compile the class and somehow let me instantiate it. This is what I am looking for. Hope this makes sense.
EDIT 6:
This is a decision that I will probably go with, because at the moment I see no alternative.
//Update Master Interface interface IMasterInterface { bool Is(Type t); IMasterInterface As(Type t); } /// <summary> /// Class to build up a final object /// </summary> class CompositionObject : IMasterInterface { ICollection<IMasterInterface> parts; CompositionObject(IMasterInterface object){ parts = new List<IMasterInterface(object);} bool Is(Type t) { foreach(IMasterInterface part in parts) { if (part is t) return true; // not sure on this off top of head } return false; } IMasterInterface As(Type t) { foreach(IMasterInterface part in parts) { if(part is t) return part; } } bool Add(IMasterInterface interface) { this.Is(typeof(interface)) return false; // don't add again this.parts.Add(interface) } }
Now my factory can simply return these composition objects, and as long as the As call is called, I can then reset it safely. I feel that there is probably a way to use generics to avoid casting.
Any specific classes that implement IMasterInterface can simply return themselves when As is called.
EDIT 3:
Thanks everyone for the comments. I am glad that I wrote my ignorance of the template; D Thanks for the clarification! I love this site and all your wonderful people!