Stop Autofac from filing IEnumerable<> - c#

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 ;)

Related

How to use Zenject to inject a dependency to a class, whose instance is defined as a field in another class

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

Avoid a global state

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.

C# make class auto-register

I have a number of types for which I need to provide custom functions that talk to the external world.
For example, I may have a Widget, and a Sprocket, and when data from the world that I don't control arrives and says "make a Widget," then I need to call a Widget.Create() function.
If the world says "make a Hammer," then I need to return a "Hammer does not exist" error.
However, the mapping between world-representation and type-name is not 1:1, so I can't simply use reflection to find the type name directly -- I need a table. (In fact, "name" may for example be a specific integer value.)
I understand how I can use a pre-defined table (or Dictionary) that maps from world-representation to class-name.
I also understand how to extend/change this table at runtime if the set of possible classes changes. (Because of rules changes, or dynamically loaded parts of the application, or whatever.)
However, all of that requires duplication -- I have to both implement my class, and then, in some other place in the code, remember to add an instance of "this class has this name in the external world."
This is a bit of a code smell, because sometime in the future I will write a new class (or delete an old class) and forget to update the table, and then spend time debugging why it doesn't work right.
I thought I could use a static member in each class which registers itself in a global table:
public static Registration Me = new Registration(typeid(MyClass), "My Name");
Unfortunately, static fields are not initialized until some function in the class is executed/accessed, so this doesn't run at start-up. (Static constructors have similar limitations, plus even more overhead in the runtime!)
The next idea was to decorate the class with a custom attribute that says "register this class in the table."
[Register("My Name")]
class MyClass : .... {
}
Unfortunately, the "Register" attribute doesn't know what class it is attached to -- only the MyClass class knows that it has the Register attribute. (This is infuriating to me, as it would be SO CONVENIENT if attributes knew where they were attached, in many, many cases. But that's an aside!)
So, the least bad implementation I can think of is to iterate all the types of all the assemblies, using reflection, and check whether they have this attribute, and if they do, register them in the table. This is, shall we say, neither elegant nor efficient.
Is there a better way to auto-register classes without having to update some other source file with a central registry?
You could also iterate over all classes matching some criteria and use RuntimeHelpers.RunClassConstructor to ensure the static initializers all get run.
Something like:
var baseType = typeof(MyType);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(a => a.GetTypes())
.Where(t => t.IsClass && !t.IsAbstract && t.IsSubclassOf(baseType));
foreach (var t in types)
{
RuntimeHelpers.RunClassConstructor(t.TypeHandle);
}
This should ensure all your
public static Registration Me = new Registration(typeid(MyClass), "My Name");
functions get called.
I have checked with other resources (that are quite knowledgeable about the internals of the CLR and IL) and it seems that this is a hole in the CLR and the C# language. There simply is no direct way of making things automatically happen on assembly load or appdomain preparation. Walking the types and finding the types that I'm interested in is the least bad way.
In fact, attributes aren't always created until some piece of code asks for them, so I can't use an attribute constructor with a type argument to auto-register, either!
This is of course not great, because if there are eight different pieces of code that each have their own kind of registration they want to do, each of those pieces have to iterate through all of the types and do the inspection on their own. The only way around that would be to give up on modularity, and make all of the different "things" that happen to types be centralized to a single walk-all-types loop at the start of the app. Third party libraries (including the MEF) still wouldn't go inside this loop, though, so there's just an unavoidable chunk of overhead here, OR an unavoidable piece of duplication -- my choice, as developer.

Can I use named and unnamed bindings together?

I have the situation where a class requires two instances of a particular injected - one general, and one more specialized (the general one can also be the specialized one, but not necessarily).
My instinct was to do something like:
Bind<IAmAThing>().To<AGeneralThing>();
Bind<IAmAThing>().To<ASpecializedThing>().Named("Special");
And then use a constructor like
MyClass(IAmAThing generalThing, [Named("Special")]IAmAThing specializedThing) {
But I'm not sure whether this is going to work and if it does, whether it will work consistently, or if there's another way of doing what I am thinking of. Essentially if I don't name an instance, can it fall back to the un-named instance? Is there a way of specifying a default like this?
Of course I can name both instances, but that seems like it's going to be a pain down the road when someone assumes they can just ask for an instance...
When you used named binding, the request must also have a name - and it must be an exact match. There's no fall back on an unnamed binding.
Are you sure, that your design requires this? How is it relevant for the consumer of the interface which instance he gets injected? Seems complicated and seems it's hiding stuff...
It looks like Niject accepts these 2 bindings but when calling Resolve<>() it throws an exception with complaints about having 2 or more bindings. The workaround I made is to have all bindings to the same interface have concrete name. Other problem is that when resolving a named binding, name does not propagate downstream, so it has to be also implemented manually. Not great.

Factory object causes stackoverflowexception due to dependancy upon itself

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.

Categories

Resources