StrangeIoC

FAQ

What is Strange? What is StrangeIoC? Is there a difference?

StrangeIoC is an Inversion-of-Control library written for C# and specifically with Unity3D in mind. It features Dependency Injection, a common event bus and an optional MVCS structure which is great for building games and apps from something quite simple up to the very, very complex. Strange is just another (colloquial) name for StrangeIoC.

What's the current version?

See here.

What versions of Unity does Strange work with? What platforms can I deploy to?

Strange works with all versions of Unity from 3.5 and up.

Supported platforms can be something of a shifting target, since Unity supports so many. Here's a list of platforms where we know Strange works, where we know it doesn't, and we're we're not entirely certain.

Strange is known to run on these.

Strange is known NOT to run on these.

We are uncertain if Strange runs on these.

These are uncertain because we've not looked into it, and to the best of our knowledge neither has anyone else. If you've experimented with any of these, we'd love to hear about it.

* Presuming the driving platform is supported.
Upcoming version 1.0 will support Unity Editor extensions built on top of StrangeIoC.
We are actively investigating getting Strange to work on consoles.
¤ Window Phone 8.1 enables only WinRT and changes most of the APIs in a breaking fashion. The amount of work necessary to make Strange work in this environment is prohibitive.

What's MVCS?

Model-View-Controller (MVC) is a standard architecture/design pattern for designing applications. The 'S' in MVCS refers to services, which suggests that MVC doesn't entirely cover the aspect of architecture that involves communicating with resources outside the application itself.

What's Inversion-of-Control? What's Dependency Injection?

Inversion-of-Control (IoC) and Dependency Injection (DI) are design patterns in which classes declare dependencies only in an abstract form, for example, by naming an Interface or a superclass, rather than the specific class they need. It is up to some other actor in the system to supply a concrete class to fulfill those dependencies. There are many forms of DI.

This “inversion” expresses the idea that, instead of a class declaring “I need a thing”, some other actor tells it “here is what you need.” Dependency Injection is the process by which a special class (the Injector) provides the things that the other classes need.

Strange fulfills DI with a runtime Reflector that analyzes each class (using System.Reflection). An Injector class then fulfills the dependencies based on the Reflector's analysis.

I already use Interfaces. That's basic OO. How is IoC any different?

"Uncle" Bob Martin explains this better than I can in this paper. The gist is that IoC is an extension of OO principles that refer not so much to how you structure your classes as to how you fulfill their dependencies. IoC structures your system so that your classes are truly Object-Oriented.

I've heard that System.Reflection is slow. Is that true?

Yes, it is slow. Strange handles this problem by caching each reflection. So no class is ever reflected more than once. We've also added two "pre-reflection" methods, which allow you to send as many reflections as you like to the reflector at a moment of your choosing (say, while the user is looking at some UI).

What's the Mediator for? Why do I need one? Why can't I just listen with a View?

Mediation is usually the most difficult part of this type of system to grok. The short answer of "why do I need a Mediator?" is "You don't." Like most parts of Strange, its use is optional. But the answer to "why isn't that functionality performed by the View?" has a better - if longer - answer.

Let's consider two common View use cases, both of which you've probably dealt with at some point:

The first case is what many/most of us experience day-to-day in any busy studio. The clock is ticking. Priorities are shifting. Carefully written design documents are thrown out the window as we struggle to meet an unrealistic schedule. In the midst of this turmoil, what part of the app is most in flux? The answer is usually the View. Change the user flow. Make this thing bigger or smaller. Move that button over there and stick in a challenge. In this scenario, Mediation serves as a layer of insulation between the View and the rest of the application. The View isn't listening for/responding to changing events from the app. Neither is the View dispatching events to the rest of the app. It carries on a private conversation with the Mediator. Chaos in the View remains in the View and tends not to infect the rest of your application. So long as your View carries on firing its events and fulfilling its API, the remainder of the app is undisturbed.

In case two, the View is not in chaos. It is, in fact, a solid, well-tested piece of code that you want to reuse over and over again (perhaps even multiple times within the same app). So imagine an Alert component with just two Events: Alert.OK and Alert.CANCEL. If you map Alert.OK and Alert.CANCEL to specific commands, your component isn't really very flexible, is it? Either these events only do one thing each within your app, or else the mapped command needs to understand the context of OK/CANCEL in order to know what to do. And you certainly don't want to keep changing the events fired by the Alert component. That wouldn't be at all flexible. But if the Alert component has a Mediator, then the Mediator can take care of the specific context. In the case of a LoginAlert, the Mediator catches OK/CANCEL events and sends MyEvent.LOGIN or MyEvent.DONT_LOGIN. In the case of an AllianceChallengeAlert, the Mediator converts OK/CANCEL to JOIN_ALLIANCE/DONT_JOIN_ALLIANCE. In this way, a component needn't know anything about the larger app. It becomes appropriately flexible and reusable.

In short, the Mediator is throwaway code. It knows about the View. It knows about the app. It keeps the View concerned solely with itself and allows greater flexibility.

What other features does Strange provide?

Strange has a big feature set for such a small library. The full feature set is on our home page.

You've explained IoC, but I've heard you say that Strange is also a Binding framework. What's that mean?

Strange is built on top of a very simple class called "Binder", which is a Collection (just like Array or Dictionary). The Binder basically attaches any item - or a set of items - to any other item or set. The 'Key' items are triggers, while the 'Value' items are results. So, in DI for example, an Interface "key" could trigger a concrete class "value". But the uses of Binder go way past DI. Strange has an EventDispatcher which is a Binder. An event triggers one or more callbacks. There's a CommandBinder in which an event triggers a command, a batch of commands or a sequence of Commands. If you think in terms of a Binder being a collection of actions/reactions, the uses are endless.

Part of my app is a Controller/Model/Service, but relies on a MonoBehaviour. How do I make this work in Strange?

This is a standard problem with Unity and anyone wanting to practice MVC (or similar) patterns. Everything MonoBehaviour is necessarily a View in some respect, since it needs to be attached to a GameObject. We don't have a definitive "best practice", but here's how we handle this in-house.

Our practice is to create hybrid solutions that inject a GameObject — for example, the ContextView — into our Controller/Model/Service, and then attach the necessary MonoBehaviour.

public class SomeService : ISomeService
{
    [Inject (ContextKeys.CONTEXT_VIEW)]
    public GameObject contextView { get; set; }

    [PostConstruct]
    public void PostConstruct()
    {
        //Now the MB is available for use within our service
        contextView.AddComponent<SomeMonoBehaviour>();
    }
}

Our ContextView therefore has a list of MonoBehaviours attached to it, i.e., all the "global" MonoBehaviour-based services.

This is far from perfect, since the Controller/Model/Service is now dependent on Unity and therefore no longer unit testable. But we don't like to treat a Model/Service like a View, just because Unity shoehorns it in that way. Also, note that the MonoBehaviour is now isolated inside the Service. If you someday find a better solution, perhaps one that doesn't require a MonoBehaviour, you have just this one class in which to refactor that change.

OK. I'm interested! How much does it cost?

Totally free! And Open Source under Apache 2. You can download it from any of the buttons on the left, pull it from GitHub, or else get it for free from the Unity Store.

I have a feature idea. Where does that...?

Way ahead of you. Add it here

I've found a bug. How do I...?

Right here cowboy.

I've fixed a bug/added a feature to StrangeIoC and would like to contribute.

We'd love to review it and consider it for inclusion. Send us a pull request via GitHub. Please note that in order for any contribution to StrangeIoC to be considered, the author must agree to contribute under the same Apache 2 license that governs StrangeIoC itself.

Do you provide support?

Strange is one of those "provided as-is" things. I'm very keen to hear your reactions and will try to make fixes. And of course you can fork the repo and send me pull requests. I hope a community will spring up around this framework and others will assist in providing mutual support. But I've got a job and unfortunately can't field requests day-to-day.

"Strange" is a strange name.

That's not a question.

OK, why did you name your framework "Strange?"

Ah! The idea came from the mathematical notion of "strange attractors" which, as best I understand them, are meant to create orderly patterns, mostly in the context of chaotic systems. I thought this was a great metaphor for what I'm doing. Plus, it's kind of funny. Don't you think it's funny?

Look, I'm the one who's supposed to be asking the questions.

Oh yeah. Sorry.