Is this the case for dynamic classes or ...?

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) /// This should be true ((princess is IEnjoyLookingAtGoods) && (princess is IConsumeGoods)) 

Essentially, I would like to tell a factory that uses interfaces to create an object. I have containers with IMasterInterface lists

 /// <summary> /// My container class for interesting objects /// </summary> class InterestingObjectContainer { public ReadOnlyCollection<IMasterInterface> InterestingObjects {get;} } 

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:

 /// <summary> /// I want to see the net population of producers and get there total production /// </summary> class ProducerProductionCalculator { // THIS IS WHERE THE MEAT OF THE QUESTION RESIDES! ProductionResults Calculate(InterestingObjectContainer interestingObject) { List<IProduceGoods> producers = interestingObject.InterestingObjects.OfType<IProduceGoods>(); // Perhaps more interest LINQ return DoSomethingWithListToAggregate(producers); } } 

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,

 /// <summary> /// Factory to create any combination of properties /// </summary> class FactoryForInterestingObjects { public static IMasterInterface Create( List<KeyValuePair</*what goes here is the interface that I want to use, what goes here are the parameter values that should be returned by the getter */>> ); } 

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;} #region Implementation of IEnjoyLookingAtGoods /*...*/ #endregion } 

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:

 /// <summary> /// Factory to create any combination of properties /// </summary> class FactoryForInterestingObjects { public static IMasterInterface Create( List<KeyValuePair<Type t, ArgSet customArguments>> interfaces)) { object baseObject; foreach(KeyValuePair<Type, ArgSet> interface in interfaces) { AddInterface(interface, object); } } private static void AddInterface(KeyValuePair<Type, ArgSet> interface, ArgSet arguments) { // Delegate this to someone else if(interface.Key is typeof(IProduceGoods)) { IProduceGoodsExtensions.AddInterface(o, interface.value); } } } public static class IProduceGoodsExtensions { public static void AddInterface(object o, ArgSet arguments) { // do something to object to make it implement IProductGoods // and make all the getters return the arguments passed in ArgSet } } 

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!

+4
source share
5 answers

Try exploring the Decorator design template. As far as I can see, it is intended for the case that you have in mind, that is, objects that may contain a mixed set of properties derived from a set of properties. In the Decorator model, each property is its own class, and you effectively dynamically combine these classes to create objects with the properties you want.

In order to implement filtering, you will need to have some kind of iterator to go through the Decorators chain to see if the one you follow is turned on for the test object.

I did not use Decorator in C #, only C ++, but I found it in a very useful and flexible way. If you find yourself creating more and more specialized classes that are intersections of property classes, I think Decorator can help.

For information on this template, see Design Design Design in C # . (And buy and read the GoF Design template book!)

+2
source

based on your update, I see that you do not seem to understand the decorator pattern.

I donโ€™t know if this is the best way to go, as if you donโ€™t have any difference in behavior, and your interfaces are static (IenjoyLookingAtGoods, IConsumeGoods, etc.), you can continue and implement them with properties on your abstract type, and just create new instances by installing them.

Decorators should be something like this

 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 || 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 || instance.Is<T>(); } } 

and if you want to get something that implements, you need to do something like this:

 IMasterInterface princess = new MasterClass() //whatever your concrete type is named princess = new ConsumesGoodsDecorator(new EnjoyLookingDecorator(princess)) var b = princess.Is<IEnjoysLookingAtGoods>() 

Edit- you can hack it like this:

  T As<T>() { return this is T ? this : instance.As<T>(); /*be careful here, the implementation in the concrete class should return null if he is not a T*/ } /*continuing the example above*/ var consumer = princess.As<IConsumesGoods>(); //this is good var producer = princess.As<IProducesGoods>(); //this will return null 

but this is disgusting, I read your question most of all, especially since these interfaces make no sense. You do not add behavior at all. Why not create a class that implements IMasterInterface, and has 4 properties with different interfaces (composition), if you do not want the princess to have IProduceGoods, then set this to null. Still hard to understand without context

NTN

+2
source

I do not like the concept of IMasterInterface, but I assume that you are simply using an abstract question for the question - I can see the past. I also have a doubt about using in your example:

 IMasterInterface princess = MyFactory.Create(IEnjoyLookingAtGoods, IEnjoyLookingAtGoodsParameters, IConsumeGoods, IConsumeGoodsParameters) /// This should be true ((princess is IEnjoyLookingAtGoods) && (princess is IConsumeGoods)) 

Shouldn't the "princess" be "something that is, and anything"?

Other than that, I think the filtering approach for implemented interface types is great.

0
source

This is a good way. And honestly, I do not see any problems with this. Interfaces are simply interfaces - they provide only a way to describe a set of common elements. The problem is that your question is pretty general and itโ€™s hard to understand what you are trying to achieve.

The factory method that accepts interfaces is rather strange. For example, we have the following code:

 public class A : IFoo { } public class B : IFoo { } var x = MyFactory.Create(IFoo); 

What will the factory create? Instance A or B?

In any case, I think the best advice I can come up with is: Do not overdo it.

0
source

When asked about a factory, you can use reflection and / or a prototype sample to execute, but only if the combination of interfaces is unique. If you have more than one specific class that can satisfy the list of requested interfaces (say, the Pricess and Prince classes), then the factory has no way of knowing what to create.

If there are no concrete classes, and you are really trying to create / create / etc an object at runtime, then this is a horse of a different color. You will probably need a common base class (or perhaps support in your master interface) to help with this use (as another poster) of the decorator approach, or perhaps using a facet type template.

0
source

All Articles