-
Notifications
You must be signed in to change notification settings - Fork 7
Dependable Mixins
When NCop crafts the proxy object it builds it with a specific constructor which accepts all mixin types.
public class CSharpDeveloperMixin : IDeveloper
{
public void Code() {
Console.WriteLine("C# coding");
}
}
public class GuitarPlayerMixin : IMusician
{
public void Play() {
Console.WriteLine("I am playing C# accord with Fender Telecaster");
}
}
[TransientComposite]
[Mixins(typeof(CSharpDeveloperMixin), typeof(GuitarPlayerMixin))]
public interface IPerson : IDeveloper, IMusician
{
}
/// Proxy
public class PersonProxyImpl : IPerson
{
private readonly IMusician musician = null;
private readonly IDeveloper developer = null;
public PersonProxyImpl() {
this.musician = new GuitarPlayerMixin();
this.developer = new CSharpDeveloperMixin();
}
}
For each mixin/implementation NCop will register also a new entry in the IoC container IDeveloper -> CSharpDeveloperMixin
.
The entry is basically a compiled factory for the mixin:
Func<IMusician> musicianFactory = () => new GuitarPlayerMixin();
Func<IDeveloper> developerFactory = () => new CSharpDeveloperMixin();
Each mixin is instantiated using its default parameterless constructor.
NCop uses the IoC container in order to inject the dependent mixins to the composite.
var musician = container.Resolve<IMusician>();
var developer = container.Resolve<IDeveloper>();
var person = container.Resolve<IPerson>(developer, musician);
By choosing the injection pattern and not creating a direct instantiation of the mixin within the composite like this:
/// Proxy
public class PersonProxyImpl : IPerson
{
private readonly IMusician musician = null;
private readonly IDeveloper developer = null;
public PersonProxyImpl() {
this.musician = new GuitarPlayerMixin();
this.developer = new CSharpDeveloperMixin();
}
}
NCop supports the possibility to register complex object graphs for each mixin.
Lets say that the CSharpDeveloperMixin is dependent upon other type.
public interface ICSharpLanguageVersion
{
int Version { get; }
}
public class CSharp5LanguageVersion : ICSharpLanguageVersion
{
public int Version {
get {
return 5;
}
}
}
public class CSharpDeveloperMixin : IDeveloper
{
private readonly ICSharpLanguageVersion languageVersion = null;
public CSharpDeveloperMixin(ICSharpLanguageVersion languageVersion) {
this.languageVersion = languageVersion;
}
public void Code() {
Console.WriteLine("C# {0} coding", languageVersion.Version);
}
}
Current version of NCop does not supports registration of complex object graphs, however you will be able to overcome it by doing couple of things:
- Instantiate new
INCopDependencyContainerAdapter
implemented by an adapter to your favorite IoC Container.
using StructureMap;
var smContainer = ObjectFactory.Container;
var container = new CompositeContainer(new CompositeRuntimeSettings {
DependencyContainerAdapter = new StructureMapAdapter(smContainer)
});
- Register the dependencies of the object graph properly using your container:
smContainer.Configure(x => {
x.For<ICSharpLanguageVersion>().Use<CSharp5LanguageVersion>();
});
The end result of the IPerson resolution would be:
using System;
using StructureMap;
using NCop.Composite.Framework;
class Program
{
static void Main(string[] args) {
IPerson person = null;
var smContainer = ObjectFactory.Container;
var container = new CompositeContainer(new CompositeRuntimeSettings {
DependencyContainerAdapter = new StructureMapAdapter(smContainer)
});
smContainer.Configure(x => {
x.For<ICSharpLanguageVersion>().Use<CSharp5LanguageVersion>();
});
container.Configure();
person = container.Resolve<IPerson>();
person.Code();
}
}
The expected output should be
"C# 5 coding"
Your end result of the code should be similar to this:
using System;
using NCop.Composite.Framework;
using NCop.Composite.Runtime;
using NCop.Mixins.Framework;
using StructureMap;
namespace NCop.Samples
{
public interface IDeveloper
{
void Code();
}
public interface IMusician
{
void Play();
}
public interface ICSharpLanguageVersion
{
int Version { get; }
}
[TransientComposite]
[Mixins(typeof(CSharpDeveloperMixin), typeof(GuitarPlayerMixin))]
public interface IPerson : IDeveloper, IMusician
{
}
public class CSharp5LanguageVersion : ICSharpLanguageVersion
{
public int Version {
get {
return 5;
}
}
}
public class GuitarPlayerMixin : IMusician
{
public void Play() {
Console.WriteLine("Playing C# accord with Fender Telecaster");
}
}
public class CSharpDeveloperMixin : IDeveloper
{
private readonly ICSharpLanguageVersion languageVersion = null;
public CSharpDeveloperMixin(ICSharpLanguageVersion languageVersion) {
this.languageVersion = languageVersion;
}
public void Code() {
Console.WriteLine("C# {0} coding", languageVersion.Version);
}
}
class Program
{
static void Main(string[] args) {
IPerson person = null;
var smContainer = ObjectFactory.Container;
var container = new CompositeContainer(new CompositeRuntimeSettings {
DependencyContainerAdapter = new StructureMapAdapter(smContainer)
});
smContainer.Configure(x => {
x.For<ICSharpLanguageVersion>().Use<CSharp5LanguageVersion>();
});
container.Configure();
person = container.Resolve<IPerson>();
person.Code();
}
}
}