Created
September 23, 2010 15:22
-
-
Save jagregory/593792 to your computer and use it in GitHub Desktop.
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
public class SomeService | |
{ | |
public string GetValues() | |
{ | |
return "huzzah"; | |
} | |
} | |
public class Person | |
{ | |
public virtual long Id { get; set; } | |
public virtual DateTime CobDate { get; set; } | |
readonly SomeService someService = Mixin.Mark<SomeService>(); | |
public virtual string GetSomeValues() | |
{ | |
return someService.GetValues(); | |
} | |
} | |
public class Mixin | |
{ | |
/// <summary> | |
/// Mark a field as a mixin target | |
/// </summary> | |
public static T Mark<T>() | |
{ | |
var proxyFactory = new ProxyFactory(); | |
return proxyFactory.CreateProxy<T>(new MixinWrapper(), typeof(IMixin)); | |
} | |
/// <summary> | |
/// Hydrate any mixin fields with an actual instance. Mixin fields are determined by: | |
/// * Being of a type that implements IMixin | |
/// * Having a value of Mixin.Mark(); | |
/// </summary> | |
public static void Hydrate<T>(T instance) | |
{ | |
var mixinTargets = typeof(T).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) | |
.Select(x => new { field = x, mixinType = x.FieldType, currentValue = x.GetValue(instance) }) | |
.Where(x => typeof(IMixin).IsAssignableFrom(x.currentValue.GetType()) || typeof(IMixin).IsAssignableFrom(x.field.FieldType)); | |
foreach (var target in mixinTargets) | |
{ | |
var mixinInstance = Activator.CreateInstance(target.mixinType); // YOUR CONTAINER HERE! | |
target.field.SetValue(instance, mixinInstance); | |
} | |
} | |
private class MixinWrapper : IInvokeWrapper | |
{ | |
public void BeforeInvoke(InvocationInfo info) | |
{ } | |
public object DoInvoke(InvocationInfo info) | |
{ | |
throw new UninjectedMixinException(); | |
} | |
public void AfterInvoke(InvocationInfo info, object returnValue) | |
{ } | |
} | |
} | |
public class UninjectedMixinException : Exception | |
{ | |
} | |
public interface IMixin | |
{} |
Usage:
In your entity:
MyService someService = Mixin.Mark<MyService>();
or
MyService someServiceThatImplementsIMixin;
After fetching/creating your entity (probably do-able using an NH interceptor):
Mixin.Hydrate(my_entity);
Ta-da, your mixin fields have values!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Random idea for mixins. Not sure this is any better than constructor injection, but it certainly is clever ;)