I have a c# factory object which creates objects through factory methods, using a list of objects as a source.
The list of objects is created like this:
public WidgetFactory()
{
widgetLibrary = new List<WidgetModel>();
//Add all widgets
widgetLibrary.Add(new ClientsWidget());
widgetLibrary.Add(new InstallationsWidget());
etc.
and various parts of my application access this list in different ways to get the type of object it needs.
But I now have a requirement that one of the objects in the list(i.e. a widget) needs to make use of the widget factory itself. Clearly this causes a circular reference.
How can I alter my design to accomodate this need?
But I now have a requirement that one of the objects in the list(i.e. a widget) needs to make use of the widget factory itself. Clearly this causes a circular reference.
How can I alter my design to accomodate this need?
Typically, objects should not rely on the factory that creates them for construction, as it causes exactly this problem. If you can push in the reference to the factory, but not use it until it's needed, it may solve the issue.
If you absolutely need to do this, then the best approach may be to lazily instantiate the objects within the factory. Instead of having your WidgetFactory contain a List<WidgetModel> internally, you could use a List<Lazy<WidgetModel>>. This would allow the individual "widgets" to only evaluate as needed, which would mean that, when the widget in question tries to reference the factory, it'll be fully loaded.
But I now have a requirement that one of the objects in the list(i.e. a widget) needs to make use of the widget factory itself. Clearly this causes a circular reference.
How can I alter my design to accomodate this need?
Your model is wrong. Once a car has left the assembly line at the NUMMI plant, it doesn't depend on the plant to operate properly.
Also, I question the design of your factory. Why are you new instances the constructor. What purpose is that serving?
You should probably tell us a little bit more about your model and why you think you need this. Odds are, properly done, you don't.
The constructor for the WidgetFactory should not be calling the constructers of the things that it is building. Instead, the WidgetFactory should have a method (BuildWidgets) that does all of the work.
Then the other objects can make some use of the factory without causing this cascade of activity to start over again.
For starters, move Widget creation out of the WidgetFactory's constructor. This should happen either in an initialization method or on-demand in a CreateWidget(Type) method.
To make the factory instance available to the Widget instances, you can do one of a few different things:
Have WidgetFactory pass 'this' when it creates the Widget
Use the singleton pattern: add a static property WidgetFactory.Instance and initialize it once; have all WidgetFactory users access the property rather than create a new instance.
Use the dependency injection pattern -- difficult to provide a short description here.
Related
I'd like to have a class that works as a collection for another class. So let's say I have FooBarCollection that has a collection of named FooBarItems. I can bind the FooBarCollection and injecting it works. The problem is that in order to keep things tidy, I'd want to do one injection within the FooBarItem class too, but in order for that to work I'd need to use a DiContainer for the instantiation, and that has too problems:
I can't do the DiContainer-based instantiation in the same line where I define the field, so I'd need two lines of code for each item in the collection. I'd like to avoid this kind of redundancy, and depending on remembering both lines of code to be added for every single item.
Passing parameters to the DiContainer instantiation isn't type-sensitive.
So is there some way that:
I could use Zenject for to inject the FooBarCollection
Have each FooBarItem under FooBarCollection to be added with a single line of code, while still being able to inject one dependency in the FoobarItem
?
Any ideas?
I am afraid I do not understand the specific situation.
It fulfill your wishes Bind an empty FooBarCollection and a Factory for FooBarItem, then call the Factory from the Spawner class to add elements to the FooBarCollection , I think.
Zenject factory Document is following.
https://github.com/modesttree/Zenject/blob/master/Documentation/Factories.md
And then, SubConatiner Document case is similar in some ways to yours maybe.
https://github.com/modesttree/Zenject/blob/master/Documentation/SubContainers.md
I'm looking for a way to stop Autofac from automatically filling an IEnumerable<> in my constructor.
For example, I have a class called School with the following constructors
public School(string name) {...}
public School(string name, IEnumerable<IStudent> students) {...}
You can use the first constructor to create the School object then use a AddStudent method to add the students to the school.
You can use the second constructor to create a School and pass in a collection of students to be added when the School object is constructed.
If I create Func<string, ISchool> schoolFactory, then call schoolFactory.Invoke("Test"), Autofac will use the second constructor and will automatically create a new Student object.
The IStudent interface and Student classes are registered with Autofac and the Student class has a default constructor. The default constructor is there because it's used in our UI when a user adds a new Student. The new Student is created with a blank name and the user can enter the name after the Student object has been created.
I tried the following ...
Remove the default constructor from Student. This works but it means I have to use a different constructor and pass in string.Empty for the student name. The main issue with this is that we have some other generic code for creating new objects that requires our classes to have default constructors. It's also not a solution for all of our classes.
Change IEnumerable<IStudent> to List<IStudent>. This works and it's what I started doing in our code, but it then forces the use of List<> instead of the generic IEnumerable<>. It's just less flexible.
Create Func<string, IEnumerable<IStudent>, ISchool> schoolFactory and use schoolFactory.Invoke("Test", Enumerable.Empty<IStudent>). This also works. It's more code, but I guess it's more explicit.
Is there a generic way I can stop Autofac from automatically filling an IEnumerable?
Nice question. The short answer is: I think it's not possible. I'm not really a fan of saying no when it comes to software engineering, so here's a longer explanation:
What you see here is a so called "implicit relationship type" in Autofac. Specifically, the one that supports resolving collections. These are implemented in Autofac via registration sources. A registration source is a way to handle registrations dynamically based on given criteria (in this case, the collection aspect of the type). You can check these sources in your container in the container.ComponentRegistry.Sources property; the last one should be the one responsible for this. So in order to disable this functionality, you must be able to somehow remove this registration source from your container, but here's the catch: this property is of type IEnumerable<IRegistrationSource>, which means that it's readonly and is not meant to be meddled with (even though it's an array at runtime).
But if you are interested in other solutions to the problem, I can recommend different approaches:
You say you have a UI and the default ctor for Student is there so that the user interface can handle this type. Sounds like you are letting your user interface interfere with the design of your object model. I suggest you try implementing some architectural patterns designed to separate UI and BLL, like MVVM or MVC. In case of MVVM for example, you might have a StudentViewModel for the UI which can have a default ctor, and you can keep the Student clean with the parameterized ctor only.
In case this is not option (as you say it is not an option for all your classes), you can try to specify the constructor when you register your type (see the docs). In this case, you can manually register the non-collection constructor and Autofac uses that:
builder.RegisterType<School>().UsingConstructor(typeof(string));
EDIT:
Or, if you are really keen on disabling the whole feature altogether, I guess you can go hardcore and open-source the s**t out of it :) Create your own fork, find the src/Autofac/ContainerBuilder.cs file and in the void RegisterDefaultAdapters(IComponentRegistry componentRegistry) method, you can see the default registration sources being added. Just delete the line that says componentRegistry.AddRegistrationSource(new CollectionRegistrationSource()); (line 247 on the develop branch in the file), then build your own and use that. Don't forget the modify the unit tests ;)
Imagine some SOA. We have a few different services, of which the OperationContext is extended by some SecureOperationContext which makes sure certain security demands are met.
Assume furthermore that sometimes we might need to know a certain property from this SecureOperationContext somewhere else, in a place where there is and won't be this SecureOperationContext. For example a username for some sort of logging purpose.
Currently we're using something that looks and smells plain dirty. The fat's dripping of in my opionion.
Now, in some 'Common' library, there is a class defined with a ThreadStatic property: Username. I guess you can catch my drift: the security stuff sets this static global variable and lo and behold we have it available for logging puproses.
This thing bugs me, but on the other hand what else to do? I was thinking about creating a method that takes a string as parameter to handle this, but then all my methods need to still read that username property, which is non-dry.
So on one hand, this way everything is handled on the background, but I'm not just quite happy having to maintain some (global) class just to achieve this.
Any tips?
I'm not sure how to put it in less abstract terms, but here goes (in pseudo).
public WebService
{
public Save(Car car)
{
// Some SecurityCOntext is known here, this holds top secret info,
// like the username
// and sets this into the golbal helper class UserNameManagemer
// car has for example a CreatedDate property (from an Interface),
//but I don't want handle do this propertyin every Create method can handled in some general piecei of code.
efcontainer.AddObjcect(car)
e.SaveChanges() ->
//Now savechanges will check the objects in the ObjectSatateManager
//and sets the apppriopriate property via the global thing.
}
}
Now what to do to rid myself of this global variable!. Passing a username to SaveChanges is undesirable ass well, since we'd then still have to manually repat this for everything, which blows.
Encapsulate the global property in a service. Define an interface for that service. Now, depend on that interface everywhere you need the data by having a constructor parameter of that type.
This is called dependency injection and is a very important concept when you want to avoid problems as the one you currently have. A dependency injection container such as Autofac can help if you have a big application, but is not strictly required.
The most important thing is to understand dependency injection and have a well-defined composition root, no matter whether you use a DI container or do it yourself.
The security stuff sets this static global variable and lo and behold we have it available for logging puproses.
This sounds like the data is determined dynamically. Note that you can still use a service to track the value. That service also knows whether the value is available or not. This way, you can better manage the temporal coupling that you have at the moment.
Edit: You can further improve the design by creating the client objects through a factory. That factory can ensure that the value is available, so it couples the lifetime of the client objects to the availability of the value. This way, you are sure to always act in a context where the value can be safely accessed.
I have a situation whereby a predecessor has created a class that is designed to handle the creation of Note entities that are added to the database to journal actions that are carried out by the system across the site.
At present, this class has been broken down into several CreateXYZNote methods that take an enum denoting a specific note type, and an instance of the model that drives that area of the site.
My problem is, there are so many types of notes, each used only in one or two places across the system. Each of the methods is huge, consisting of a small amount of common code, and specifics (e.g. the textual content of the note) are held within a series of switch statements based on an enum. Extremely hard to find the code relating to specific notes, and very hard to maintain at present, and it's only going to grow as new types of notes find their way into the system over time.
Has anyone got any advice or patterns that could help with this sort of situation?
The simplest solution I can think of is that I have a set of profiles held outside of this class as a dictionary (keyed by the enum values) that define the title, description, categories etc. for the notes, and this class then becomes just a means of looking up those values and creating the note, but it just feels like I'm moving the problem to another place rather than resolving it.
You could use a NoteFactory that has a INote Create(NoteType type) method. The factory could depend on a Dictionary keyed by NoteType that the factory uses to find and return the appropriate Note. This way you avoid a non-OCP switch statement.
The factory can be injected with the dictionary, using an IoC container helps here, or you can create the dictionary in the constructor.
i'm working on a tile editor. In the editor you can load a tile map. Each tile map can have multiple layers. A tile map has a list of it's layers. I now need tile map properties in the layer class (things like tile width/height e.g.). I'm now asking myself what is the best way to do this.
I could make a bidirectional relationship by introducing a tilemap property in the layer class, so that i have access to everything i need from there. But then i would have to take care of two sides of the relationship.
I could give all the needed properties to the layer class with the constructor, but then they basicly become layer properties (aka they are different objects for every layer).
Same as 2 but give the properties to the layer with "ref" paramter.
I could make a class called something like TileMapLayerProperties where i put all the properties in and then pass the object to the layer classes. Advantage would be that all the properties would be the same and only the tileMapLayerProperties-reference would be per instance. Another advantage would be the "definition" of the layer constructor becoming much shorter.
So any suggestions / tips would be appreciated.
A bi-directional association (1) might be OK or not, depending on what properties and methods a tile map contains and what a layer should be able to know and access. If a tile map has a DeleteAllLayers method and layers should not be able to call it, then layers cannot have direct access to their parent.
Creating a dedicated property object (4) seems more clean to me. That way you have one object with all necessary information that you can pass around, but it does not contain more than that, especially it does not allow calling destructive methods etc.
Passing the properties to the constructor (2) is similar to (4), but more verbose and less object-oriented. It's fine when you have 1 or 2 properties, but with more than a few it gets ugly and unmaintainable.
But there is another problem: If the properties are of immutable types (e.g. int, string), then the layers do not see changes made in the map. They only see their private copy!
I don't understand (3). How does the ref keyword change (2)? It only allows the callee to change the value of a variable passed by the caller. Or do you mean objects with reference types?
Another solution
Interfaces would be another way to solve this. You could create a ITileMapLayerProperties interface that provides all the properties and pass it to the layer's constructor. The map could either implement the interface itself or contain a TileMapLayerProperties object that implements the interface. But the layer does not need to know this.
Option 2 would work for what you are trying to do, and you may not need to include the 'ref' keyword.
I'm curious, what kind of datamembers are you trying to access from the child classes? If they are collections then you may not need the 'ref' keyword.
Another option would be to make the parent class static, but I'm not sure if this is the outcome you're looking for. Can you load more than one tile map at a time? If not, consider the static class option.
I think option is 3 is better. You can pass a reference of your ParentClass to the ChildClass and can have directly access to all public properties. I suggested it better because what ever changes you will make whether from ChildClass or ParentClass, all other layers will inherit those changes.