Created
March 12, 2017 10:49
-
-
Save nonnb/82df8e127cf7d6c6e4d6d6032566903c to your computer and use it in GitHub Desktop.
StackOverflow21285090 - Alternatives to Abstract Factory pattern using Ninject
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Windows.Forms; | |
using Ninject; | |
using Ninject.Modules; | |
namespace WindowsFormsApplication5 | |
{ | |
public partial class Form1 : Form | |
{ | |
public Form1() | |
{ | |
InitializeComponent(); | |
} | |
private void button1_Click(object sender, EventArgs e) | |
{ | |
// Obviously I'm abusing Ninject as a Service Locator here rather than a dependency injector | |
// but the build up of dependencies is still demonstrated. | |
IKernel kernel = new StandardKernel(new FooModule()); | |
var theScreen = kernel.Get<Screen>(); | |
// Like abstract factory, the actual concrete class returned can be flavoured, | |
// either by a parameter, attributes, or even ambient context. | |
theScreen.AddButton(ButtonType.CancelButton); | |
theScreen.AddButton(ButtonType.OKButton); | |
theScreen.AddButton(ButtonType.ExitButton); | |
} | |
} | |
public interface IButton | |
{ | |
} | |
public class OkButton : IButton | |
{ | |
} | |
public class CancelButton : IButton | |
{ | |
} | |
public class ExitButton : IButton | |
{ | |
} | |
public enum ButtonType | |
{ | |
OKButton, | |
CancelButton, | |
ExitButton | |
}; | |
public class FooModule : NinjectModule | |
{ | |
public override void Load() | |
{ | |
Bind<Func<ButtonType, IButton>>() | |
.ToMethod( | |
context => | |
{ | |
return (buttonType => | |
{ | |
switch (buttonType) | |
{ | |
case ButtonType.OKButton: | |
return new OkButton(); | |
case ButtonType.CancelButton: | |
return new CancelButton(); | |
case ButtonType.ExitButton: | |
return new ExitButton(); | |
default: | |
throw new ArgumentException("buttonType"); | |
} | |
}); | |
}); | |
// TODO : It would be cleaner to separate each of the predicates into its own registration | |
// http://stackoverflow.com/a/15270745/314291 | |
// But doing this elegantly eludes me | |
// Bind<Func<ButtonType, IButton>>() | |
// .ToMethod(context => x => new OkButton()) | |
// .When(request => request.Parameters.First().GetValue() == ButtonType.OKButton); | |
// Bind<Func<ButtonType, IButton>>() | |
// .ToMethod(context => x => new CancelButton()) | |
// .When(request => request.Parameters.First().GetValue() == ButtonType.CancelButton); | |
} | |
} | |
public class Screen | |
{ | |
private readonly Func<ButtonType, IButton> _buttonResolver; | |
private readonly IList<IButton> _buttons; | |
public Screen(Func<ButtonType, IButton> buttonResolver) | |
{ | |
_buttonResolver = buttonResolver; | |
_buttons = new List<IButton>(); | |
} | |
public void AddButton(ButtonType type) | |
{ | |
var newButton = _buttonResolver(type); | |
_buttons.Add(newButton); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment