I'm trying to use Zenject in Unity. I have an interface and several implementations of it.
I want to inject with ID but also that the implementation will have the tick interface since it's not a MonoBehaviour.
So I have an IAttacker interface and a MeleeAttackImpl implementation.
Container.Bind<IAttacker>().WithId(AttackerTypeEnum.MELEEE).To<MeleeAttackImpl>().AsTransient();
I want to add
Container.BindInterfacesTo<MeleeAttackImpl>().AsTransient();
But it creates 2 different objects instead of instances that have the Tick interface and bind them to IAttacker.
If you want to bind an interface to a determined implementation, why do you use two bindings?
If you want only one instance of the object I would try:
Container.BindInterfacesAndSelfTo<MeleeAttackImpl>().AsSingle();
or:
Container.Bind<IAttacker>().To<MeleeAttackImpl>().AsSingle();
As Single() In the case you need the same instance provided from the container along the app (like a singleton).
From the documentation:
"AsTransient - Will not re-use the instance at all. Every time ContractType is requested, the DiContainer will execute the given construction method again."
Many times intance is created in the binding itself. So maybe from the two binding two instances are created, one from each binding.
In case you need to create instances dynamically with all their dependencies resolved, what you need a is Factory.
Related
I've edited the question to make what I want to obtain clearer.
Here's the original question:
I'm working on a class that inherits from Control which will be used in my View and includes some Dependency Properties.
One of these DPs is an IEnumerable(Of RfidTag) and will be bound to an ObservableCollection(Of RfidTag) inside the VM.
The class RfidTag is defined as public class in the same file where the VM's class resides.
The questions are:
1. is it a good practice to expose a VM-related class to a Control class?
2. is the VM source file a good place for the RfidTag class?
UPDATE 1
In my application logic (I think I could say in my Model) there is an event published throught an Eventaggregator. The event's payload is a List of ModelRfidTag (that is the model class).
My VM subscribes to this event and I made the RfidTag class to wrap my Model class and provides some additional properties related only to the VM.
When the event handler inside the VM is executed, it makes an ObservableCollection(Of RfidTag) bindable from the view.
Then in the View I've a bounch of my control instances like that
<c:RfidTagPresenter
TagPosition="1"
Collection="{Binding RfidTagList, Mode=OneWay}" />
Then in my RfidTagPresenter (the class that inherits from Control) I've a DP of type RfidTag (called RfidTagResult) that returns the object in the OC which has the Position property (property available inside the RfidTag class) equal to the value set by the TagPosition DP.
In this way, the ControlTemplate of the RfidTagPresenter can bind its elements to the desired object.
This is the simplification of what I want to make. In the actual application there are some other DPs on which the RfidTagResult selection is performed
UPDATE 2
After a bit of research, seem that I can solve one problem with an indexed property that return (in the get method) the object from the collection I want to bind.
However a problem still exist: My control need to have a DP of type of RfidTag so that the relative ControlTemplate can bind to the property declared in the RfidTag class.
So: Is it possible (read: a good practice) to have a DP of a type that is a VM related class?
In other words: Can a custom control know about the class type used by the VM?
I will try to go all over your question (if I miss something let me know) but first you should explain the purpose of binding a Collection in a control as a DP.
is it a good practice to expose a VM-related class to a Control class?
RfidTag, I suppose, is a Model. What you are really doing here is binding a Model in your control which go against the MVVM pattern. You should think about the next question... Do you really need all your RfidTag to be shown in the View ? If you need to show a name, an ID... you could just create an IEnumerable<string> as DP (which is correct) and then in your VM instead of an ObservableCollection<RfidTag> you would have an ObservableCollection<string>.
Some simple theory. In MVVM, VM adapts the Model to the View. So your VM should have everything that will be shown in your View.
is the VM source file a good place for the RfidTag class?
RfidTag is a Model so there's no better place for it :)
I have splitted my application into two main areas.
Part(A)
PartStashContainer(B)
The content of A should be set based on what user wants.
So basically i can have 1..N classes which could be used in Class URI of Part in application model.
I don't know if i should replace the whole Part(A) with new dynamically created Part(C) which has content i want, or i should somehow to modify the existing Part (call setContributionURI, or setObject methods on Part object?).
It does make more sense to me to modify the existing Part, because it is defined in Application model and therefore already describing the location where the content should be.
Possible solutions:
Modify the Part object so it "reload" its content based on new setup (But how? Can setContributionURI or setObject methods help?)
Remove the old Part and add dynamically on same place in Application model the new Part (using EModelService and EPartService).
other solution??
If you want to reuse the Part then do something like:
MPart part = find or inject your part
MyClass myClass = (MyClass)part.getObject();
... call a method of MyClass to change the contents
MyClass is the class you specify for the object in the application model. You should add a method to that to let you change the contents.
Don't try to call setObject, this is really only for use by Eclipse. I don't think setContributionURI would do anything after the part is created (but I am not sure).
If you want to use different classes for the different data then you really should use different Parts.
I understand the following Ninject registration:
kernel.Bind<ISomeType>().To<SomeTypeImplementation>();
which tells Ninect to fulfill requests for ISomeType by using SomeTypeImplementation.
However I'm not sure what the following is good for.
kernel.Bind<ApplicationDbContext>().ToSelf();
Which was suggested that I use from this question:
What ninject binding should I use?
It makes ApplicationDbContext "self-bindable". If you don't have an interface to bind to, you can bind to the class itself. It's more useful if you add a scope to the call such as:
kernel.Bind<ApplicationDbContext>().ToSelf().InRequestScope();
Any time it sees the ApplicationDbContext that needs to be injected, it will reuse the same object as long as it is in the same HTTP request.
The default scope is transient, which means that any time a class requests ApplicationDbContext it will create a new instance of it. This can be problematic if you have two classes that both need to use the context in the same transaction. That is why you will often see it done with InRequestScope().
By self-binding a type, you enable that type for the following:
Lifecycle Management by the container.
Enable the container to inject dependencies into other types that depend on the self-bound type, and inject dependencies of this type into its instances likewise.
Very useful if you just have one single implementation or you don't need to use abstractions for some reason.
It appears that Unity IoC defaults to creating a new instance of an object when it resolves a type. But my question is there someway to be explicit and tell my container that whenever I have it resolve an object type to give me a new instance of said type?
IE i want to be explicit and force the container to make sure theInstance is a new instance each time it resolves type:MyNewObject (or all types for that matter)
MyNewObject theInstance = container.Resolve<MyNewObject>();
Yes it is easily configurable by a TransientLifetimeManager
When you register a class should have something like
container.Register<IMyNewObject, MyMewObject>(new TransientLifetimeManager());
//or
container.Register<MyMewObject>(new TransientLifetimeManager())
If you're applying IoC principles properly, your class declares its dependencies and then the container handles the lifecycles of them. For example, you want to grab an HttpRequest object and the container handles providing the current thread-local one, or whatever.
Your code shouldn't really have to care about the life-cycle of its dependencies, as it should never be responsible for clearing up after them or what-have-you (all of that should be encapsulated in the dependency itself, and invoked by the container when it is shut down).
However, if you do need to care in your code about whether you get a singleton instance or a per-injected instance of the same type, I like to be explicit about it by using the type system itself, just as the Guice container for Java does with its Provider pattern. I've created a Guice-style IProvider<T> interface that I use to do this, and I just wire it up with a simple static factory method for them like so:
Provider.Of<Foo>(() => { /* Code to return a Foo goes here */})
I have an object instance, and I want to end up with a MEF catalog that contains that object instance, exported as a specific interface type. How can I do this?
TypeCatalog doesn't seem workable here, because (a) it creates a new instance instead of using an existing one, and (b) it requires the type to have an [Export] attribute. In my case, the instance comes from MEF's metadata system, so MEF creates the underlying type and I can't add attributes to it.
As far as I can tell, the usual advice is, if you've got an existing instance, you should add it to the container (e.g. via CompositionBatch), not to the catalog. But when I add this instance, I'm also adding an entire AssemblyCatalog worth of types, all in the same operation. I'll also want to be able to remove all of these types later. It makes more sense to me to bundle everything into an AggregateCatalog. That way, I can add both the assembly and the instance in one atomic operation, and I can remove them all again the same way.
For example:
// Bootstrapper code to initialize MEF:
public void Configure() {
_selectedGameCatalog = new AggregateCatalog();
var globalCatalog = new AggregateCatalog(_selectedGameCatalog);
_container = new CompositionContainer(globalCatalog);
// ... more MEF initialization ...
}
// Sometime later, I want to add more stuff to the MEF ecosystem:
public void SelectGame(Lazy<Game, IGameMetadata> entry) {
var newCatalog = new AggregateCatalog();
// Make the assembly available to import:
newCatalog.Catalogs.Add(new AssemblyCatalog(entry.Value.GetType().Assembly));
// I also want the metadata to be available to import:
IGameMetadata metadata = entry.Metadata;
newCatalog.Catalogs.Add(MakeCatalogFromInstance<IGameMetadata>(metadata));
// Replace whatever game was selected before:
_selectedGameCatalog.Catalogs.Clear();
_selectedGameCatalog.Catalogs.Add(newCatalog);
}
The part I don't know how to do is "MakeCatalogFromInstance". How can I create a catalog that contains an existing instance (registered as a specific type)?
Or, alternatively, if I'm going about this all wrong, is there a better way to plug an entire catalog and an existing instance all into MEF at the same time, with the ability to unplug them all again later and replace them with something else?
I think it's probably best to add the types to the catalog and then add the instance to the container.
Catalogs contain part definitions. Part definitions are used to create parts. (The types for this are ComposablePartDefinition and ComposablePart.) So you could theoretically write your own catalog and a part definition that always returned a part corresponding to the instance when CreatePart was called. But catalogs weren't really designed to be used this way.
For prosperity...
MEF devivides the chores of what type info is to be used (catalog) from the actual running object instances (container). To me it is a logical descicion, especially when you setup a more complex MEF environment in your application.
If you want the ability to 'change' containers on the fly, I would suggest you try to use hierarchical containers. The root catalog/container is filled with static types and any of the child containers can be filled with each specific set of meta types you need for your game.
Hope it helps,
Marc